diff --git a/Makefile.am b/Makefile.am index e219f0e9b0..f9a747d30e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -147,7 +147,7 @@ endif lib_LTLIBRARIES = libfreeswitch.la libfreeswitch_la_CFLAGS = $(CORE_CFLAGS) $(AM_CFLAGS) libfreeswitch_la_LDFLAGS = -version-info 1:0:0 $(AM_LDFLAGS) $(PLATFORM_CORE_LDFLAGS) -libfreeswitch_la_LIBADD = $(CORE_LIBS) $(PLATFORM_CORE_LIBS) +libfreeswitch_la_LIBADD = $(CORE_LIBS) $(PLATFORM_CORE_LIBS) libs/sofia-sip/libsofia-sip-ua/sdp/.libs/libsdp.a libs/sofia-sip/libsofia-sip-ua/su/.libs/libsu.a libfreeswitch_la_DEPENDENCIES = $(BUILT_SOURCES) if HAVE_ODBC diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index 4ee5f1880e..21a80a194f 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -44,8 +44,6 @@ typedef enum { DTMF_NONE } switch_core_media_dtmf_t; - - typedef enum { SM_NDLB_ALLOW_BAD_IANANAME = (1 << 0), SM_NDLB_ALLOW_NONDUP_SDP = (1 << 1), @@ -65,39 +63,78 @@ typedef enum { SCMF_T38_PASSTHRU, SCMF_LIBERAL_DTMF, SCMF_SUPPRESS_CNG, + SCMF_DISABLE_RTP_AUTOADJ, + SCMF_PASS_RFC2833, + SCMF_AUTOFLUSH, + SCMF_REWRITE_TIMESTAMPS, SCMF_MAX } switch_core_media_flag_t; struct switch_media_handle_s; typedef enum { - STYPE_INTVAL, - STYPE_UINTVAL, - STYPE_CHARVAL, -} scm_type_t; + STUN_FLAG_SET = (1 << 0), + STUN_FLAG_PING = (1 << 1), + STUN_FLAG_FUNNY = (1 << 2) +} STUNFLAGS; typedef enum { - SCM_INBOUND_CODEC_STRING, - SCM_OUTBOUND_CODEC_STRING, - SCM_AUTO_RTP_BUGS, - SCM_MANUAL_RTP_BUGS, - SCM_MAX -} scm_param_t; + VAD_IN = (1 << 0), + VAD_OUT = (1 << 1) +} switch_core_media_vflag_t; -#define switch_media_get_param_int(_h, _p) *(int *)switch_media_get_param(_h, _p) -#define switch_media_get_param_uint(_h, _p) *(uint32_t *)switch_media_get_param(_h, _p) -#define switch_media_get_param_char(_h, _p) (char *)switch_media_get_param(_h, _p) +typedef struct switch_core_media_params_s { + uint32_t rtp_timeout_sec; + uint32_t rtp_hold_timeout_sec; + uint32_t dtmf_delay; + uint32_t codec_flags; + int reinvite; + switch_core_media_NDLB_t ndlb; + switch_rtp_bug_flag_t auto_rtp_bugs; + + char *inbound_codec_string; + char *outbound_codec_string; + + char *timer_name; + + char *remote_sdp_str; + char *early_sdp; + char *local_sdp_str; + char *last_sdp_str; + + char *stun_ip; + switch_port_t stun_port; + uint32_t stun_flags; + + char *jb_msec; + + switch_core_media_vflag_t vflags; + + switch_rtp_bug_flag_t manual_rtp_bugs; + switch_rtp_bug_flag_t manual_video_rtp_bugs; + + char *rtcp_audio_interval_msec; + char *rtcp_video_interval_msec; + + + char *extrtpip; + char *rtpip; + + char *remote_ip; + int remote_port; + + char *extsipip; + char *local_network; + + +} switch_core_media_params_t; - -SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t **smhp, switch_core_session_t *session); +SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t **smhp, switch_core_session_t *session, switch_core_media_params_t *params); SWITCH_DECLARE(switch_media_handle_t *) switch_core_session_get_media_handle(switch_core_session_t *session); SWITCH_DECLARE(switch_status_t) switch_core_session_clear_media_handle(switch_core_session_t *session); SWITCH_DECLARE(switch_status_t) switch_core_session_media_handle_ready(switch_core_session_t *session); -SWITCH_DECLARE(void) switch_media_handle_set_ndlb(switch_media_handle_t *smh, switch_core_media_NDLB_t flag); -SWITCH_DECLARE(void) switch_media_handle_clear_ndlb(switch_media_handle_t *smh, switch_core_media_NDLB_t flag); -SWITCH_DECLARE(int32_t) switch_media_handle_test_ndlb(switch_media_handle_t *smh, switch_core_media_NDLB_t flag); SWITCH_DECLARE(void) switch_media_handle_set_media_flag(switch_media_handle_t *smh, switch_core_media_flag_t flag); SWITCH_DECLARE(void) switch_media_handle_clear_media_flag(switch_media_handle_t *smh, switch_core_media_flag_t flag); SWITCH_DECLARE(int32_t) switch_media_handle_test_media_flag(switch_media_handle_t *smh, switch_core_media_flag_t flag); @@ -113,8 +150,6 @@ SWITCH_DECLARE(void) switch_core_session_get_recovery_crypto_key(switch_core_ses SWITCH_DECLARE(void) switch_core_media_set_rtp_session(switch_core_session_t *session, switch_media_type_t type, switch_rtp_t *rtp_session); -SWITCH_DECLARE(void) switch_media_set_param(switch_media_handle_t *smh, scm_param_t param, ...); -SWITCH_DECLARE(void *) switch_media_get_param(switch_media_handle_t *smh, scm_param_t param); SWITCH_DECLARE(const char *)switch_core_media_get_codec_string(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_media_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str); SWITCH_DECLARE(switch_t38_options_t *) switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m); @@ -126,6 +161,14 @@ SWITCH_DECLARE(void) switch_core_media_pass_zrtp_hash2(switch_core_session_t *al SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session, int sendonly); SWITCH_DECLARE(void) switch_core_media_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session); SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *session, const char *r_sdp, uint8_t *proceed, int reinvite, int codec_flags, switch_payload_t default_te); +SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_session_t *session, int force); +SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_t *session, int force, uint32_t codec_flags); +SWITCH_DECLARE(void) switch_core_media_check_video_codecs(switch_core_session_t *session); +SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session_t *session, switch_frame_t **frame, + switch_io_flag_t flags, int stream_id, switch_media_type_t type); +SWITCH_DECLARE(switch_status_t) switch_core_media_write_frame(switch_core_session_t *session, + 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_END_EXTERN_C #endif diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 1a69c4c256..f6ca438a6b 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1288,6 +1288,8 @@ typedef enum { CF_PROTO_HOLD, //TFLAG_SIP_HOLD CF_HOLD_LOCK, CF_VIDEO_POSSIBLE,//TFLAG_VIDEO + CF_NOTIMER_DURING_BRIDGE, + CF_PASS_RFC2833, /* 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 diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 93a232b9cd..209ae2577b 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -944,15 +944,13 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) { private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session); - switch_channel_t *channel = switch_core_session_get_channel(session); - uint32_t sanity = 1000; switch_assert(tech_pvt != NULL); if (sofia_test_flag(tech_pvt, TFLAG_HUP)) { return SWITCH_STATUS_FALSE; } - +#if 0 while (!(tech_pvt->video_read_codec.implementation && switch_rtp_ready(tech_pvt->video_rtp_session) && !switch_channel_test_flag(channel, CF_REQ_MEDIA))) { switch_ivr_parse_all_messages(tech_pvt->session); @@ -963,59 +961,19 @@ static switch_status_t sofia_read_video_frame(switch_core_session_t *session, sw return SWITCH_STATUS_GENERR; } } +#endif - tech_pvt->video_read_frame.datalen = 0; - if (sofia_test_flag(tech_pvt, TFLAG_IO)) { - switch_status_t status; + return switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_VIDEO); - if (!sofia_test_flag(tech_pvt, TFLAG_RTP)) { - return SWITCH_STATUS_GENERR; - } - - switch_assert(tech_pvt->rtp_session != NULL); - tech_pvt->video_read_frame.datalen = 0; - - while (sofia_test_flag(tech_pvt, TFLAG_IO) && tech_pvt->video_read_frame.datalen == 0) { - tech_pvt->video_read_frame.flags = SFF_NONE; - - status = switch_rtp_zerocopy_read_frame(tech_pvt->video_rtp_session, &tech_pvt->video_read_frame, flags); - if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { - if (status == SWITCH_STATUS_TIMEOUT) { - if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) { - sofia_media_toggle_hold(tech_pvt, 0); - sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD); - switch_channel_clear_flag(channel, CF_LEG_HOLDING); - } - switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_MEDIA_TIMEOUT); - } - return status; - } - - if (tech_pvt->video_read_frame.datalen > 0) { - break; - } - } - } - - if (tech_pvt->video_read_frame.datalen == 0) { - *frame = NULL; - return SWITCH_STATUS_GENERR; - } - - *frame = &tech_pvt->video_read_frame; - - return SWITCH_STATUS_SUCCESS; } static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) { private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session); - switch_channel_t *channel = switch_core_session_get_channel(session); - int wrote = 0; - switch_assert(tech_pvt != NULL); +#if 0 while (!(tech_pvt->video_read_codec.implementation && switch_rtp_ready(tech_pvt->video_rtp_session))) { if (switch_channel_ready(channel)) { switch_yield(10000); @@ -1023,6 +981,7 @@ static switch_status_t sofia_write_video_frame(switch_core_session_t *session, s return SWITCH_STATUS_GENERR; } } +#endif if (sofia_test_flag(tech_pvt, TFLAG_HUP)) { return SWITCH_STATUS_FALSE; @@ -1036,11 +995,8 @@ static switch_status_t sofia_write_video_frame(switch_core_session_t *session, s return SWITCH_STATUS_SUCCESS; } - if (!switch_test_flag(frame, SFF_CNG)) { - wrote = switch_rtp_write_frame(tech_pvt->video_rtp_session, frame); - } - - return wrote > 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_GENERR; + return switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_VIDEO); + } static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) @@ -1105,7 +1061,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f if (status == SWITCH_STATUS_TIMEOUT) { if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) { - sofia_media_toggle_hold(tech_pvt, 0); + switch_core_media_toggle_hold(session, 0); sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD); switch_channel_clear_flag(channel, CF_LEG_HOLDING); } @@ -1274,7 +1230,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f tech_pvt->codec_ms = codec_ms; } - if (sofia_media_tech_set_codec(tech_pvt, 2) != SWITCH_STATUS_SUCCESS) { + if (switch_core_media_set_codec(tech_pvt->session, 2, tech_pvt->profile->codec_flags) != SWITCH_STATUS_SUCCESS) { *frame = NULL; return SWITCH_STATUS_GENERR; } @@ -1906,7 +1862,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi tech_pvt->video_rm_encoding = NULL; switch_channel_clear_flag(tech_pvt->channel, CF_VIDEO_POSSIBLE); sofia_media_tech_prepare_codecs(tech_pvt); - sofia_media_check_video_codecs(tech_pvt); + switch_core_media_check_video_codecs(tech_pvt->session); sofia_media_set_local_sdp(tech_pvt, NULL, 0, NULL, 1); sofia_set_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE); sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA); @@ -2446,7 +2402,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi { if (msg->numeric_arg) { - sofia_media_toggle_hold(tech_pvt, 1); + switch_core_media_toggle_hold(session, 1); } else { sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 8f6a083316..0f07da4915 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -199,9 +199,7 @@ typedef enum { PFLAG_AUTH_ALL, PFLAG_FULL_ID, PFLAG_MULTIREG_CONTACT, - PFLAG_PASS_RFC2833, PFLAG_DISABLE_TRANSCODING, - PFLAG_REWRITE_TIMESTAMPS, PFLAG_RUNNING, PFLAG_RESPAWN, PFLAG_MULTIREG, @@ -218,10 +216,6 @@ typedef enum { PFLAG_AGGRESSIVE_NAT_DETECTION, PFLAG_RECIEVED_IN_NAT_REG_CONTACT, PFLAG_3PCC, - PFLAG_DISABLE_RTP_AUTOADJ, - PFLAG_FUNNY_STUN, - PFLAG_STUN_ENABLED, - PFLAG_STUN_AUTO_DISABLE, PFLAG_3PCC_PROXY, PFLAG_CALLID_AS_UUID, PFLAG_UUID_AS_CALLID, @@ -230,7 +224,6 @@ typedef enum { PFLAG_DISABLE_SRV, PFLAG_DISABLE_SRV503, PFLAG_DISABLE_NAPTR, - PFLAG_AUTOFLUSH, PFLAG_NAT_OPTIONS_PING, PFLAG_ALL_REG_OPTIONS_PING, PFLAG_MESSAGE_QUERY_ON_REGISTER, @@ -282,12 +275,6 @@ typedef enum { PFLAG_NDLB_EXPIRES_IN_REGISTER_RESPONSE = (1 << 6) } sofia_NDLB_t; -typedef enum { - STUN_FLAG_SET = (1 << 0), - STUN_FLAG_PING = (1 << 1), - STUN_FLAG_FUNNY = (1 << 2) -} STUNFLAGS; - typedef enum { TFLAG_IO, TFLAG_CHANGE_MEDIA, @@ -299,9 +286,6 @@ typedef enum { TFLAG_BYE, TFLAG_ANS, TFLAG_EARLY_MEDIA, - TFLAG_VAD_IN, - TFLAG_VAD_OUT, - TFLAG_VAD, TFLAG_3PCC, TFLAG_READY, TFLAG_REINVITE, @@ -326,7 +310,6 @@ typedef enum { TFLAG_T38_PASSTHRU, TFLAG_RECOVERED, TFLAG_AUTOFLUSH_DURING_BRIDGE, - TFLAG_NOTIMER_DURING_BRIDGE, TFLAG_JB_PAUSED, TFLAG_3PCC_INVITE, TFLAG_NOREPLY, @@ -575,9 +558,6 @@ struct sofia_profile { char *presence_hosts; char *presence_privacy; char *challenge_realm; - char *rtcp_audio_interval_msec; - char *rtcp_video_interval_msec; - char *jb_msec; char *pnp_prov_url; char *pnp_notify_profile; sofia_cid_type_t cid_type; @@ -603,7 +583,6 @@ struct sofia_profile { switch_memory_pool_t *pool; su_root_t *s_root; sip_alias_node_t *aliases; - switch_payload_t te; switch_payload_t cng_pt; uint32_t codec_flags; switch_mutex_t *ireg_mutex; @@ -684,6 +663,7 @@ struct sofia_profile { uint32_t rtp_digit_delay; switch_queue_t *event_queue; switch_thread_t *thread; + switch_core_media_vflag_t vflags; }; struct private_object { @@ -695,6 +675,7 @@ struct private_object { switch_core_session_t *session; switch_channel_t *channel; switch_media_handle_t *media_handle; + switch_core_media_params_t *mparams; switch_frame_t read_frame; char *codec_order[SWITCH_MAX_CODECS]; @@ -710,17 +691,9 @@ struct private_object { switch_caller_profile_t *caller_profile; uint32_t timestamp_send; switch_rtp_t *rtp_session; - uint32_t ssrc; + uint32_t video_ssrc; sofia_profile_t *profile; - char *local_sdp_audio_ip; - switch_port_t local_sdp_audio_port; - char *remote_sdp_audio_ip; - switch_port_t remote_sdp_audio_port; - char *adv_sdp_audio_ip; - switch_port_t adv_sdp_audio_port; - char *proxy_sdp_audio_ip; - switch_port_t proxy_sdp_audio_port; char *reply_contact; char *from_uri; char *to_uri; @@ -738,10 +711,6 @@ struct private_object { char *iananame; char *rm_fmtp; char *fmtp_out; - char *remote_sdp_str; - char *early_sdp; - char *local_sdp_str; - char *last_sdp_str; char *dest; char *dest_to; char *key; @@ -757,16 +726,12 @@ struct private_object { char *local_url; char *gateway_name; char *record_route; - char *extrtpip; - char *stun_ip; char *route_uri; char *x_freeswitch_support_remote; char *x_freeswitch_support_local; char *last_sent_callee_id_name; char *last_sent_callee_id_number; - char *rtpip; - switch_port_t stun_port; - uint32_t stun_flags; + unsigned long rm_rate; switch_payload_t pt; switch_mutex_t *flag_mutex; @@ -795,16 +760,12 @@ struct private_object { switch_payload_t video_pt; unsigned long video_rm_rate; uint32_t video_codec_ms; - char *remote_sdp_video_ip; - switch_port_t remote_sdp_video_port; char *video_rm_fmtp; switch_payload_t video_agreed_pt; char *video_fmtp_out; uint32_t video_count; switch_core_media_dtmf_t dtmf_type; int q850_cause; - char *remote_ip; - int remote_port; int got_bye; int hold_laps; switch_thread_id_t locker; @@ -1012,8 +973,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot); void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now); void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now); void sofia_reg_unregister(sofia_profile_t *profile); -switch_status_t sofia_glue_ext_address_lookup(sofia_profile_t *profile, private_object_t *tech_pvt, char **ip, switch_port_t *port, - const char *sourceip, switch_memory_pool_t *pool); + void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp); switch_call_cause_t sofia_glue_sip_cause_to_freeswitch(int status); @@ -1033,7 +993,6 @@ char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile, switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata); char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex, char *sql, char *resbuf, size_t len); -void sofia_media_check_video_codecs(private_object_t *tech_pvt); void sofia_glue_del_profile(sofia_profile_t *profile); switch_status_t sofia_glue_add_profile(char *key, sofia_profile_t *profile); @@ -1106,18 +1065,17 @@ char *sofia_glue_find_parameter_value(switch_core_session_t *session, const char char *sofia_glue_create_via(switch_core_session_t *session, const char *ip, switch_port_t port, sofia_transport_t transport); char *sofia_glue_create_external_via(switch_core_session_t *session, sofia_profile_t *profile, sofia_transport_t transport); char *sofia_glue_strip_uri(const char *str); -int sofia_glue_check_nat(sofia_profile_t *profile, const char *network_ip); + int sofia_glue_transport_has_tls(const sofia_transport_t tp); const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name); switch_status_t sofia_media_build_crypto(private_object_t *tech_pvt, int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction); void sofia_media_tech_patch_sdp(private_object_t *tech_pvt); -switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, const char *sdp_str); void sofia_presence_event_thread_start(void); void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot); void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id); void sofia_reg_check_sync(sofia_profile_t *profile); -switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt, int force); -switch_status_t sofia_media_tech_set_video_codec(private_object_t *tech_pvt, int force); + + char *sofia_glue_get_register_host(const char *uri); const char *sofia_glue_strip_proto(const char *uri); void sofia_glue_del_gateway(sofia_gateway_t *gp); @@ -1126,9 +1084,7 @@ void sofia_glue_del_every_gateway(sofia_profile_t *profile); void sofia_reg_send_reboot(sofia_profile_t *profile, const char *callid, const char *user, const char *host, const char *contact, const char *user_agent, const char *network_ip); void sofia_glue_restart_all_profiles(void); -int sofia_media_toggle_hold(private_object_t *tech_pvt, int sendonly); const char *sofia_state_string(int state); -switch_status_t sofia_media_tech_set_codec(private_object_t *tech_pvt, int force); void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout); void sofia_glue_set_udptl_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist); @@ -1175,8 +1131,6 @@ switch_status_t sip_dig_function(_In_opt_z_ const char *cmd, _In_opt_ switch_cor const char *sofia_gateway_status_name(sofia_gateway_status_t status); void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int status, const char *phrase); uint32_t sofia_reg_reg_count(sofia_profile_t *profile, const char *user, const char *host); -void sofia_media_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session); -switch_t38_options_t *sofia_media_extract_t38_options(switch_core_session_t *session, const char *r_sdp); char *sofia_media_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type); int sofia_glue_tech_simplify(private_object_t *tech_pvt); switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *profile, const char *user, const char *host); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index ea42f7731b..f4bec11606 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -3920,27 +3920,13 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } else if (!strcasecmp(var, "aggressive-nat-detection") && switch_true(val)) { sofia_set_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION); } else if (!strcasecmp(var, "disable-rtp-auto-adjust") && switch_true(val)) { - sofia_set_pflag(profile, PFLAG_DISABLE_RTP_AUTOADJ); + if (switch_true(val)) { + sofia_set_media_flag(profile, SCMF_DISABLE_RTP_AUTOADJ); + } else { + 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; - } else if (!strcasecmp(var, "NDLB-funny-stun")) { - if (switch_true(val)) { - sofia_set_pflag(profile, PFLAG_FUNNY_STUN); - } else { - sofia_clear_pflag(profile, PFLAG_FUNNY_STUN); - } - } else if (!strcasecmp(var, "stun-enabled")) { - if (switch_true(val)) { - sofia_set_pflag(profile, PFLAG_STUN_ENABLED); - } else { - sofia_clear_pflag(profile, PFLAG_STUN_ENABLED); - } - } else if (!strcasecmp(var, "stun-auto-disable")) { - if (switch_true(val)) { - sofia_set_pflag(profile, PFLAG_STUN_AUTO_DISABLE); - } else { - sofia_clear_pflag(profile, PFLAG_STUN_AUTO_DISABLE); - } } 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")) { @@ -3958,12 +3944,11 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } } else if (!strcasecmp(var, "vad")) { if (!strcasecmp(val, "in")) { - sofia_set_flag(profile, TFLAG_VAD_IN); + profile->vflags |= VAD_IN; } else if (!strcasecmp(val, "out")) { - sofia_set_flag(profile, TFLAG_VAD_OUT); + profile->vflags |= VAD_OUT; } else if (!strcasecmp(val, "both")) { - sofia_set_flag(profile, TFLAG_VAD_IN); - sofia_set_flag(profile, TFLAG_VAD_OUT); + profile->vflags |= VAD_OUT | VAD_IN; } else if (strcasecmp(val, "none")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid option %s for VAD\n", val); } @@ -5235,7 +5220,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ); switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL); } else if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38 && sip->sip_payload && sip->sip_payload->pl_data) { - switch_t38_options_t *t38_options = sofia_media_extract_t38_options(session, sip->sip_payload->pl_data); + switch_t38_options_t *t38_options = switch_core_media_extract_t38_options(session, sip->sip_payload->pl_data); if (!t38_options) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Could not parse T.38 options from sdp.\n"); @@ -5274,7 +5259,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status } } - sofia_media_copy_t38_options(t38_options, other_session); + switch_core_media_copy_t38_options(t38_options, other_session); } } @@ -5450,7 +5435,7 @@ void *SWITCH_THREAD_FUNC media_on_hold_thread_run(switch_thread_t *thread, void switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); } - sofia_media_toggle_hold(tech_pvt, 1); + switch_core_media_toggle_hold(session, 1); } switch_core_session_rwunlock(other_session); } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index f72eee39e2..9dedfbc672 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -279,12 +279,22 @@ 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); - switch_media_handle_create(&tech_pvt->media_handle, session); - switch_media_handle_set_ndlb(tech_pvt->media_handle, tech_pvt->profile->ndlb); - switch_media_handle_set_media_flags(tech_pvt->media_handle, tech_pvt->profile->media_flags); + tech_pvt->mparams->ndlb = tech_pvt->profile->ndlb; + tech_pvt->mparams->inbound_codec_string = profile->inbound_codec_string; + tech_pvt->mparams->outbound_codec_string = profile->outbound_codec_string; + tech_pvt->mparams->auto_rtp_bugs = profile->auto_rtp_bugs; + tech_pvt->mparams->timer_name = profile->timer_name; + tech_pvt->mparams->vflags = profile->vflags; + tech_pvt->mparams->manual_rtp_bugs = profile->manual_rtp_bugs; + tech_pvt->mparams->manual_video_rtp_bugs = profile->manual_video_rtp_bugs; + tech_pvt->mparams->extsipip = profile->extsipip; + tech_pvt->mparams->local_network = profile->local_network; + - switch_media_set_param(tech_pvt->media_handle, SCM_INBOUND_CODEC_STRING, profile->inbound_codec_string); - switch_media_set_param(tech_pvt->media_handle, SCM_OUTBOUND_CODEC_STRING, profile->inbound_codec_string); + switch_media_handle_create(&tech_pvt->media_handle, session, &tech_pvt->mparams); + switch_media_handle_set_media_flags(tech_pvt->media_handle, tech_pvt->profile->media_flags); + + switch_core_session_set_private(session, tech_pvt); @@ -295,100 +305,6 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t * } -switch_status_t sofia_glue_ext_address_lookup(sofia_profile_t *profile, private_object_t *tech_pvt, char **ip, switch_port_t *port, - const char *sourceip, switch_memory_pool_t *pool) -{ - char *error = ""; - switch_status_t status = SWITCH_STATUS_FALSE; - int x; - switch_port_t myport = *port; - const char *var; - int funny = 0; - switch_port_t stun_port = SWITCH_STUN_DEFAULT_PORT; - char *stun_ip = NULL; - - if (!sourceip) { - return status; - } - - if (!strncasecmp(sourceip, "host:", 5)) { - status = (*ip = switch_stun_host_lookup(sourceip + 5, pool)) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; - } else if (!strncasecmp(sourceip, "stun:", 5)) { - char *p; - - if (!sofia_test_pflag(profile, PFLAG_STUN_ENABLED)) { - *ip = switch_core_strdup(pool, tech_pvt->rtpip); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Trying to use STUN but its disabled!\n"); - goto out; - } - - stun_ip = strdup(sourceip + 5); - - if ((p = strchr(stun_ip, ':'))) { - int iport; - *p++ = '\0'; - iport = atoi(p); - if (iport > 0 && iport < 0xFFFF) { - stun_port = (switch_port_t) iport; - } - } - - if (zstr(stun_ip)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! NO STUN SERVER\n"); - goto out; - } - - for (x = 0; x < 5; x++) { - if (sofia_test_pflag(profile, PFLAG_FUNNY_STUN) || - (tech_pvt && (var = switch_channel_get_variable(tech_pvt->channel, "funny_stun")) && switch_true(var))) { - error = "funny"; - funny++; - } - if ((status = switch_stun_lookup(ip, port, stun_ip, stun_port, &error, pool)) != SWITCH_STATUS_SUCCESS) { - switch_yield(100000); - } else { - break; - } - } - if (status != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! %s:%d [%s]\n", stun_ip, stun_port, error); - goto out; - } - if (!*ip) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! No IP returned\n"); - goto out; - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Success [%s]:[%d]\n", *ip, *port); - status = SWITCH_STATUS_SUCCESS; - if (tech_pvt) { - if (myport == *port && !strcmp(*ip, tech_pvt->rtpip)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Not Required ip and port match. [%s]:[%d]\n", *ip, *port); - if (sofia_test_pflag(profile, PFLAG_STUN_AUTO_DISABLE)) { - sofia_clear_pflag(profile, PFLAG_STUN_ENABLED); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN completely disabled.\n"); - } - } else { - tech_pvt->stun_ip = switch_core_session_strdup(tech_pvt->session, stun_ip); - tech_pvt->stun_port = stun_port; - tech_pvt->stun_flags |= STUN_FLAG_SET; - if (funny) { - tech_pvt->stun_flags |= STUN_FLAG_FUNNY; - } - } - } - } else { - *ip = (char *) sourceip; - status = SWITCH_STATUS_SUCCESS; - } - - out: - - switch_safe_free(stun_ip); - - return status; -} - - const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name) { sip_unknown_t *un; @@ -472,69 +388,6 @@ switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt, int forc } -switch_status_t sofia_glue_tech_choose_video_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; /* 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_video_port) { - return SWITCH_STATUS_SUCCESS; - } - } - - /* Release the local sdp port */ - if (tech_pvt->local_sdp_video_port) { - switch_rtp_release_port(tech_pvt->rtpip, tech_pvt->local_sdp_video_port); - } - - /* Request a local port from the core's allocator */ - if (!(tech_pvt->local_sdp_video_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; - } - - sdp_port = tech_pvt->local_sdp_video_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_video_port, SWITCH_NAT_UDP, &sdp_port, SWITCH_FALSE); - - /* Find an IP address to use */ - if (!(use_ip = switch_channel_get_variable(tech_pvt->channel, "rtp_adv_video_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_video_port = sdp_port; - switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip); - switch_channel_set_variable_printf(tech_pvt->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, "%d", sdp_port); - - return SWITCH_STATUS_SUCCESS; -} - sofia_transport_t sofia_glue_str2transport(const char *str) { if (!strncasecmp(str, "udp", 3)) { @@ -726,14 +579,7 @@ char *sofia_glue_strip_uri(const char *str) return r; } -int sofia_glue_check_nat(sofia_profile_t *profile, const char *network_ip) -{ - switch_assert(network_ip); - return (profile->extsipip && - !switch_check_network_list_ip(network_ip, "loopback.auto") && - !switch_check_network_list_ip(network_ip, profile->local_network)); -} int sofia_glue_transport_has_tls(const sofia_transport_t tp) { @@ -825,172 +671,6 @@ char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char return new_uri; } -#define RA_PTR_LEN 512 -switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, const char *sdp_str) -{ - const char *err; - char rip[RA_PTR_LEN] = ""; - char rp[RA_PTR_LEN] = ""; - char rvp[RA_PTR_LEN] = ""; - char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL, *pe; - int x; - const char *val; - switch_status_t status = SWITCH_STATUS_FALSE; - - if (zstr(sdp_str)) { - sdp_str = tech_pvt->remote_sdp_str; - } - - if (zstr(sdp_str)) { - goto end; - } - - if ((p = (char *) switch_stristr("c=IN IP4 ", sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", sdp_str))) { - ip_ptr = p + 9; - } - - if ((p = (char *) switch_stristr("m=audio ", sdp_str))) { - port_ptr = p + 8; - } - - if ((p = (char *) switch_stristr("m=image ", sdp_str))) { - char *tmp = p + 8; - - if (tmp && atoi(tmp)) { - port_ptr = tmp; - } - } - - if ((p = (char *) switch_stristr("m=video ", sdp_str))) { - vid_port_ptr = p + 8; - } - - if (!(ip_ptr && port_ptr)) { - goto end; - } - - p = ip_ptr; - pe = p + strlen(p); - x = 0; - while (x < sizeof(rip) - 1 && p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F'))) { - rip[x++] = *p; - p++; - if (p >= pe) { - goto end; - } - } - - p = port_ptr; - x = 0; - while (x < sizeof(rp) - 1 && p && *p && (*p >= '0' && *p <= '9')) { - rp[x++] = *p; - p++; - if (p >= pe) { - goto end; - } - } - - p = vid_port_ptr; - x = 0; - while (x < sizeof(rvp) - 1 && p && *p && (*p >= '0' && *p <= '9')) { - rvp[x++] = *p; - p++; - if (p >= pe) { - goto end; - } - } - - if (!(*rip && *rp)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "invalid SDP\n"); - goto end; - } - - tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, rip); - tech_pvt->remote_sdp_audio_port = (switch_port_t) atoi(rp); - - if (*rvp) { - tech_pvt->remote_sdp_video_ip = switch_core_session_strdup(tech_pvt->session, rip); - tech_pvt->remote_sdp_video_port = (switch_port_t) atoi(rvp); - } - - if (tech_pvt->remote_sdp_video_ip && tech_pvt->remote_sdp_video_port) { - if (!strcmp(tech_pvt->remote_sdp_video_ip, rip) && atoi(rvp) == tech_pvt->remote_sdp_video_port) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Remote video address:port [%s:%d] has not changed.\n", - tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); - } else { - switch_channel_set_flag(tech_pvt->channel, CF_VIDEO_POSSIBLE); - switch_channel_set_flag(tech_pvt->channel, CF_VIDEO); - if (switch_rtp_ready(tech_pvt->video_rtp_session)) { - const char *rport = NULL; - switch_port_t remote_rtcp_port = 0; - - if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_video_rtcp_port"))) { - remote_rtcp_port = (switch_port_t)atoi(rport); - } - - - if (switch_rtp_set_remote_address(tech_pvt->video_rtp_session, tech_pvt->remote_sdp_video_ip, - tech_pvt->remote_sdp_video_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n", - tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port); - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && - !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { - /* Reactivate the NAT buster flag. */ - switch_rtp_set_flag(tech_pvt->video_rtp_session, SWITCH_RTP_FLAG_AUTOADJ); - } - if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) { - tech_pvt->check_frames = 0; - } - } - } - } - } - - if (switch_rtp_ready(tech_pvt->rtp_session)) { - 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); - const char *rport = NULL; - switch_port_t remote_rtcp_port = 0; - - 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, "Remote address:port [%s:%d] has not changed.\n", - tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); - switch_goto_status(SWITCH_STATUS_BREAK, end); - } - - if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port"))) { - remote_rtcp_port = (switch_port_t)atoi(rport); - } - - - if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, - tech_pvt->remote_sdp_audio_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err); - status = SWITCH_STATUS_GENERR; - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n", - tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && - !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { - /* Reactivate the NAT buster flag. */ - switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); - } - if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) { - tech_pvt->check_frames = 0; - } - status = SWITCH_STATUS_SUCCESS; - } - } - - end: - - return status; -} - - - char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix) { char *extra_headers = NULL; @@ -1159,7 +839,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) cid_name = caller_profile->caller_id_name; cid_num = caller_profile->caller_id_number; sofia_media_tech_prepare_codecs(tech_pvt); - sofia_media_check_video_codecs(tech_pvt); + switch_core_media_check_video_codecs(tech_pvt->session); check_decode(cid_name, session); check_decode(cid_num, session); @@ -2416,7 +2096,7 @@ int sofia_recover_callback(switch_core_session_t *session) tech_pvt->pt = tech_pvt->agreed_pt = (switch_payload_t)atoi(tmp); } - sofia_media_tech_set_codec(tech_pvt, 1); + switch_core_media_set_codec(tech_pvt->session, 1, tech_pvt->profile->codec_flags); tech_pvt->adv_sdp_audio_ip = tech_pvt->extrtpip = (char *) ip; tech_pvt->adv_sdp_audio_port = tech_pvt->local_sdp_audio_port = (switch_port_t)atoi(port); diff --git a/src/mod/endpoints/mod_sofia/sofia_media.c b/src/mod/endpoints/mod_sofia/sofia_media.c index 9176315211..e0cef9e323 100644 --- a/src/mod/endpoints/mod_sofia/sofia_media.c +++ b/src/mod/endpoints/mod_sofia/sofia_media.c @@ -183,7 +183,7 @@ void sofia_media_proxy_codec(switch_core_session_t *session, const char *r_sdp) tech_pvt->iananame = switch_core_session_strdup(tech_pvt->session, map->rm_encoding); tech_pvt->rm_rate = map->rm_rate; tech_pvt->codec_ms = ptime; - sofia_media_tech_set_codec(tech_pvt, 0); + switch_core_media_set_codec(tech_pvt->session, 0, tech_pvt->profile->codec_flags); break; } @@ -212,1450 +212,17 @@ uint8_t sofia_media_negotiate_sdp(switch_core_session_t *session, const char *r_ return t; } - -#if 0 -uint8_t sofia_media_negotiate_sdp(switch_core_session_t *session, const char *r_sdp) -{ - uint8_t match = 0; - switch_payload_t best_te = 0, te = 0, cng_pt = 0; - private_object_t *tech_pvt = switch_core_session_get_private(session); - sdp_media_t *m; - sdp_attribute_t *attr; - int first = 0, last = 0; - int ptime = 0, dptime = 0, maxptime = 0, dmaxptime = 0; - int sendonly = 0, recvonly = 0; - int greedy = 0, x = 0, skip = 0, mine = 0; - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *val; - const char *crypto = NULL; - int got_crypto = 0, got_video_crypto = 0, got_audio = 0, got_avp = 0, got_video_avp = 0, got_video_savp = 0, got_savp = 0, got_udptl = 0; - int scrooge = 0; - sdp_parser_t *parser = NULL; - sdp_session_t *sdp; - int reneg = 1; - const switch_codec_implementation_t **codec_array; - int total_codecs; - - - codec_array = tech_pvt->codecs; - total_codecs = tech_pvt->num_codecs; - - - if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) { - return 0; - } - - if (!(sdp = sdp_session(parser))) { - sdp_parser_free(parser); - return 0; - } - - switch_assert(tech_pvt != NULL); - - greedy = !!sofia_test_media_flag(tech_pvt->profile, SCMF_CODEC_GREEDY); - scrooge = !!sofia_test_media_flag(tech_pvt->profile, SCMF_CODEC_SCROOGE); - - if ((val = switch_channel_get_variable(channel, "sip_codec_negotiation"))) { - if (!strcasecmp(val, "generous")) { - greedy = 0; - scrooge = 0; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : generous\n" ); - } else if (!strcasecmp(val, "greedy")) { - greedy = 1; - scrooge = 0; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : greedy\n" ); - } else if (!strcasecmp(val, "scrooge")) { - scrooge = 1; - greedy = 1; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : scrooge\n" ); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation ignored invalid value : '%s' \n", val ); - } - } - - if ((tech_pvt->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) { - - if (tech_pvt->profile->auto_rtp_bugs & RTP_BUG_CISCO_SKIP_MARK_BIT_2833) { - - if (strstr(tech_pvt->origin, "CiscoSystemsSIP-GW-UserAgent")) { - tech_pvt->rtp_bugs |= RTP_BUG_CISCO_SKIP_MARK_BIT_2833; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n"); - } - } - - if (tech_pvt->profile->auto_rtp_bugs & RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833) { - if (strstr(tech_pvt->origin, "Sonus_UAC")) { - tech_pvt->rtp_bugs |= RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, - "Hello,\nI see you have a Sonus!\n" - "FYI, Sonus cannot follow the RFC on the proper way to send DTMF.\n" - "Sadly, my creator had to spend several hours figuring this out so I thought you'd like to know that!\n" - "Don't worry, DTMF will work but you may want to ask them to fix it......\n"); - } - } - } - - if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_liberal_dtmf")) && switch_true(val)) { - sofia_set_flag_locked(tech_pvt, TFLAG_LIBERAL_DTMF); - } - - if ((m = sdp->sdp_media) && - (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive || - (m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")))) { - sendonly = 2; /* global sendonly always wins */ - } - - for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) { - if (zstr(attr->a_name)) { - continue; - } - - if (!strcasecmp(attr->a_name, "sendonly")) { - sendonly = 1; - switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "recvonly"); - } else if (!strcasecmp(attr->a_name, "inactive")) { - sendonly = 1; - switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "inactive"); - } else if (!strcasecmp(attr->a_name, "recvonly")) { - switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "sendonly"); - recvonly = 1; - - if (switch_rtp_ready(tech_pvt->rtp_session)) { - switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, 0); - tech_pvt->max_missed_hold_packets = 0; - tech_pvt->max_missed_packets = 0; - } else { - switch_channel_set_variable(tech_pvt->channel, "rtp_timeout_sec", "0"); - switch_channel_set_variable(tech_pvt->channel, "rtp_hold_timeout_sec", "0"); - } - } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendrecv")) { - sendonly = 0; - } else if (!strcasecmp(attr->a_name, "ptime")) { - dptime = atoi(attr->a_value); - } else if (!strcasecmp(attr->a_name, "maxptime")) { - dmaxptime = atoi(attr->a_value); - } - } - - if (sendonly != 1 && recvonly != 1) { - switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", NULL); - } - - - if (sofia_test_media_flag(tech_pvt->profile, SCMF_DISABLE_HOLD) || - ((val = switch_channel_get_variable(tech_pvt->channel, "sip_disable_hold")) && switch_true(val))) { - sendonly = 0; - } else { - - if (!tech_pvt->hold_laps) { - tech_pvt->hold_laps++; - if (sofia_media_toggle_hold(tech_pvt, sendonly)) { - reneg = sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_HOLD); - - if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_renegotiate_codec_on_hold"))) { - reneg = switch_true(val); - } - } - - } - } - - if (reneg) { - reneg = sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE); - - if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_renegotiate_codec_on_reinvite"))) { - reneg = switch_true(val); - } - } - - if (!reneg && tech_pvt->num_negotiated_codecs) { - codec_array = tech_pvt->negotiated_codecs; - total_codecs = tech_pvt->num_negotiated_codecs; - } else if (reneg) { - tech_pvt->num_codecs = 0; - sofia_media_tech_prepare_codecs(tech_pvt); - codec_array = tech_pvt->codecs; - total_codecs = tech_pvt->num_codecs; - } - - if (switch_stristr("T38FaxFillBitRemoval:", r_sdp) || switch_stristr("T38FaxTranscodingMMR:", r_sdp) || - switch_stristr("T38FaxTranscodingJBIG:", r_sdp)) { - switch_channel_set_variable(tech_pvt->channel, "t38_broken_boolean", "true"); - } - - switch_core_media_find_zrtp_hash(session, sdp); - switch_core_media_pass_zrtp_hash(session); - - for (m = sdp->sdp_media; m; m = m->m_next) { - sdp_connection_t *connection; - switch_core_session_t *other_session; - - ptime = dptime; - maxptime = dmaxptime; - - if (m->m_proto == sdp_proto_srtp) { - if (m->m_type == sdp_media_audio) { - got_savp++; - } else { - got_video_savp++; - } - } else if (m->m_proto == sdp_proto_rtp) { - if (m->m_type == sdp_media_audio) { - got_avp++; - } else { - got_video_avp++; - } - } else if (m->m_proto == sdp_proto_udptl) { - got_udptl++; - } - - if (got_udptl && m->m_type == sdp_media_image && m->m_port) { - switch_t38_options_t *t38_options = switch_core_media_process_udptl(tech_pvt->session, sdp, m); - - if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_NEGOTIATED)) { - match = 1; - goto done; - } - - if (switch_true(switch_channel_get_variable(channel, "refuse_t38"))) { - switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38); - match = 0; - goto done; - } else { - const char *var = switch_channel_get_variable(channel, "t38_passthru"); - int pass = sofia_test_pflag(tech_pvt->profile, PFLAG_T38_PASSTHRU); - - - if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38)) { - sofia_set_flag(tech_pvt, TFLAG_NOREPLY); - } - - if (var) { - if (!(pass = switch_true(var))) { - if (!strcasecmp(var, "once")) { - pass = 2; - } - } - } - - if ((pass == 2 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) || - !sofia_test_flag(tech_pvt, TFLAG_REINVITE) || - switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || - switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) || - !switch_rtp_ready(tech_pvt->rtp_session)) { - pass = 0; - } - - if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) { - private_object_t *other_tech_pvt = switch_core_session_get_private(other_session); - switch_channel_t *other_channel = switch_core_session_get_channel(other_session); - switch_core_session_message_t *msg; - char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session); - switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session); - char tmp[32] = ""; - - if (switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_broken_boolean")) && - switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_pass_broken_boolean"))) { - switch_channel_set_variable(other_channel, "t38_broken_boolean", "true"); - } - - tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, t38_options->remote_ip); - tech_pvt->remote_sdp_audio_port = t38_options->remote_port; - - if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n", - switch_channel_get_name(tech_pvt->channel)); - } else { - const char *err = NULL; - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n", - switch_channel_get_name(tech_pvt->channel), - remote_host, remote_port, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); - - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); - - if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, - tech_pvt->remote_sdp_audio_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err); - switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); - } - - } - - - - sofia_media_copy_t38_options(t38_options, other_session); - - sofia_set_flag(tech_pvt, TFLAG_T38_PASSTHRU); - sofia_set_flag(other_tech_pvt, TFLAG_T38_PASSTHRU); - - msg = switch_core_session_alloc(other_session, sizeof(*msg)); - msg->message_id = SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA; - msg->from = __FILE__; - msg->string_arg = switch_core_session_strdup(other_session, r_sdp); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing T38 req to other leg.\n%s\n", r_sdp); - switch_core_session_queue_message(other_session, msg); - switch_core_session_rwunlock(other_session); - } - } - - - /* do nothing here, mod_fax will trigger a response (if it's listening =/) */ - match = 1; - goto done; - } else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) { - sdp_rtpmap_t *map; - - for (attr = m->m_attributes; attr; attr = attr->a_next) { - - if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) { - switch_channel_set_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port", attr->a_value); - } else if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) { - ptime = atoi(attr->a_value); - } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) { - maxptime = atoi(attr->a_value); - } else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) { - int crypto_tag; - - if (!(tech_pvt->profile->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) && - !switch_true(switch_channel_get_variable(tech_pvt->channel, "sip_allow_crypto_in_avp"))) { - if (m->m_proto != sdp_proto_srtp) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n"); - match = 0; - goto done; - } - } - - crypto = attr->a_value; - crypto_tag = atoi(crypto); - - got_crypto = switch_core_session_check_incoming_crypto(tech_pvt->session, - SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_MEDIA_TYPE_AUDIO, crypto, crypto_tag); - - } - } - - if (got_crypto && !got_avp) { - switch_channel_set_variable(tech_pvt->channel, SOFIA_CRYPTO_MANDATORY_VARIABLE, "true"); - switch_channel_set_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_VARIABLE, "true"); - } - - connection = sdp->sdp_connection; - if (m->m_connections) { - connection = m->m_connections; - } - - if (!connection) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n"); - match = 0; - break; - } - - greed: - x = 0; - - if (tech_pvt->rm_encoding && !(sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF))) { // && !sofia_test_flag(tech_pvt, TFLAG_REINVITE)) { - char *remote_host = tech_pvt->remote_sdp_audio_ip; - switch_port_t remote_port = tech_pvt->remote_sdp_audio_port; - int same = 0; - - if (switch_rtp_ready(tech_pvt->rtp_session)) { - remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session); - remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session); - } - - for (map = m->m_rtpmaps; map; map = map->rm_next) { - if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { - match = (map->rm_pt == tech_pvt->pt) ? 1 : 0; - } else { - match = strcasecmp(switch_str_nil(map->rm_encoding), tech_pvt->iananame) ? 0 : 1; - } - - if (match && connection->c_address && remote_host && !strcmp(connection->c_address, remote_host) && m->m_port == remote_port) { - same = 1; - } else { - same = 0; - break; - } - } - - if (same) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, - "Our existing sdp is still good [%s %s:%d], let's keep it.\n", - tech_pvt->rm_encoding, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); - got_audio = 1; - } else { - match = 0; - got_audio = 0; - } - } - - for (map = m->m_rtpmaps; map; map = map->rm_next) { - int32_t i; - uint32_t near_rate = 0; - const switch_codec_implementation_t *mimp = NULL, *near_match = NULL; - const char *rm_encoding; - uint32_t map_bit_rate = 0; - int codec_ms = 0; - switch_codec_fmtp_t codec_fmtp = { 0 }; - - if (x++ < skip) { - continue; - } - - if (!(rm_encoding = map->rm_encoding)) { - rm_encoding = ""; - } - - if (!strcasecmp(rm_encoding, "telephone-event")) { - if (!best_te || map->rm_rate == tech_pvt->rm_rate) { - best_te = (switch_payload_t) map->rm_pt; - } - } - - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && !cng_pt && !strcasecmp(rm_encoding, "CN")) { - cng_pt = (switch_payload_t) map->rm_pt; - if (tech_pvt->rtp_session) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", cng_pt); - switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt); - } - } - - if (match) { - continue; - } - - if (greedy) { - first = mine; - last = first + 1; - } else { - first = 0; - last = tech_pvt->num_codecs; - } - - codec_ms = ptime; - - if (maxptime && (!codec_ms || codec_ms > maxptime)) { - codec_ms = maxptime; - } - - if (!codec_ms) { - codec_ms = switch_default_ptime(rm_encoding, map->rm_pt); - } - - map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt); - - if (!ptime && !strcasecmp(map->rm_encoding, "g723")) { - codec_ms = 30; - } - - if (zstr(map->rm_fmtp)) { - if (!strcasecmp(map->rm_encoding, "ilbc")) { - codec_ms = 30; - map_bit_rate = 13330; - } - } else { - if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) { - if (codec_fmtp.bits_per_second) { - map_bit_rate = codec_fmtp.bits_per_second; - } - if (codec_fmtp.microseconds_per_packet) { - codec_ms = (codec_fmtp.microseconds_per_packet / 1000); - } - } - } - - - for (i = first; i < last && i < total_codecs; i++) { - const switch_codec_implementation_t *imp = codec_array[i]; - uint32_t bit_rate = imp->bits_per_second; - uint32_t codec_rate = imp->samples_per_second; - if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) { - continue; - } - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u]/[%s:%d:%u:%d:%u]\n", - rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms, map_bit_rate, - imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate); - if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { - match = (map->rm_pt == imp->ianacode) ? 1 : 0; - } else { - match = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1; - } - - if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate && strcasecmp(map->rm_encoding, "ilbc")) { - /* if a bit rate is specified and doesn't match, this is not a codec match, except for ILBC */ - match = 0; - } - - if (match && map->rm_rate && codec_rate && map->rm_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") || !strcasecmp(map->rm_encoding, "pcmu"))) { - /* if the sampling rate is specified and doesn't match, this is not a codec match for G.711 */ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sampling rates have to match for G.711\n"); - match = 0; - } - - if (match) { - if (scrooge) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, - "Bah HUMBUG! Sticking with %s@%uh@%ui\n", - imp->iananame, imp->samples_per_second, imp->microseconds_per_packet / 1000); - } else { - if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || map->rm_rate != codec_rate) { - near_rate = map->rm_rate; - near_match = imp; - match = 0; - continue; - } - } - mimp = imp; - break; - } - } - - if (!match && near_match) { - const switch_codec_implementation_t *search[1]; - char *prefs[1]; - char tmp[80]; - int num; - - switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second, - codec_ms); - - prefs[0] = tmp; - num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1); - - if (num) { - mimp = search[0]; - } else { - mimp = near_match; - } - - if (!maxptime || mimp->microseconds_per_packet / 1000 <= maxptime) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh\n", - mimp->iananame, mimp->microseconds_per_packet / 1000, mimp->samples_per_second); - match = 1; - } else { - mimp = NULL; - match = 0; - } - - } - - if (!match && greedy) { - skip++; - continue; - } - - if (mimp) { - char tmp[50]; - const char *mirror = switch_channel_get_variable(tech_pvt->channel, "rtp_mirror_remote_audio_codec_payload"); - - tech_pvt->rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding); - tech_pvt->iananame = switch_core_session_strdup(session, (char *) mimp->iananame); - tech_pvt->pt = (switch_payload_t) map->rm_pt; - tech_pvt->rm_rate = mimp->samples_per_second; - tech_pvt->codec_ms = mimp->microseconds_per_packet / 1000; - tech_pvt->bitrate = mimp->bits_per_second; - tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(session, (char *) connection->c_address); - tech_pvt->rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp); - tech_pvt->remote_sdp_audio_port = (switch_port_t) m->m_port; - tech_pvt->agreed_pt = (switch_payload_t) map->rm_pt; - tech_pvt->num_negotiated_codecs = 0; - tech_pvt->negotiated_codecs[tech_pvt->num_negotiated_codecs++] = mimp; - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); - tech_pvt->audio_recv_pt = (switch_payload_t)map->rm_pt; - - if (!switch_true(mirror) && - switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && - (!sofia_test_flag(tech_pvt, TFLAG_REINVITE) || sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE))) { - sofia_media_get_offered_pt(tech_pvt, mimp, &tech_pvt->audio_recv_pt); - } - - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->audio_recv_pt); - switch_channel_set_variable(tech_pvt->channel, "rtp_audio_recv_pt", tmp); - - } - - if (match) { - if (sofia_media_tech_set_codec(tech_pvt, 1) == SWITCH_STATUS_SUCCESS) { - got_audio = 1; - } else { - match = 0; - } - } - } - - if (!best_te && (sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, - "No 2833 in SDP. Liberal DTMF mode adding %d as telephone-event.\n", tech_pvt->profile->te); - best_te = tech_pvt->profile->te; - } - - if (best_te) { - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - te = tech_pvt->te = (switch_payload_t) best_te; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send payload to %u\n", best_te); - if (tech_pvt->rtp_session) { - switch_rtp_set_telephony_event(tech_pvt->rtp_session, (switch_payload_t) best_te); - switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", best_te); - } - } else { - te = tech_pvt->recv_te = tech_pvt->te = (switch_payload_t) best_te; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send/recv payload to %u\n", te); - if (tech_pvt->rtp_session) { - switch_rtp_set_telephony_event(tech_pvt->rtp_session, te); - switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", te); - switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, te); - switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_recv_payload", "%d", te); - } - } - } else { - /* by default, use SIP INFO if 2833 is not in the SDP */ - if (!switch_false(switch_channel_get_variable(channel, "sip_info_when_no_2833"))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No 2833 in SDP. Disable 2833 dtmf and switch to INFO\n"); - switch_channel_set_variable(tech_pvt->channel, "dtmf_type", "info"); - tech_pvt->dtmf_type = DTMF_INFO; - te = tech_pvt->recv_te = tech_pvt->te = 0; - } else { - switch_channel_set_variable(tech_pvt->channel, "dtmf_type", "none"); - tech_pvt->dtmf_type = DTMF_NONE; - te = tech_pvt->recv_te = tech_pvt->te = 0; - } - } - - - if (!match && greedy && mine < total_codecs) { - mine++; - skip = 0; - goto greed; - } - - } else if (m->m_type == sdp_media_video && m->m_port) { - sdp_rtpmap_t *map; - const char *rm_encoding; - const switch_codec_implementation_t *mimp = NULL; - int vmatch = 0, i; - switch_channel_set_variable(tech_pvt->channel, "video_possible", "true"); - - connection = sdp->sdp_connection; - if (m->m_connections) { - connection = m->m_connections; - } - - if (!connection) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n"); - match = 0; - break; - } - - for (map = m->m_rtpmaps; map; map = map->rm_next) { - - for (attr = m->m_attributes; attr; attr = attr->a_next) { - if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) { - //framerate = atoi(attr->a_value); - } - if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) { - switch_channel_set_variable(tech_pvt->channel, "sip_remote_video_rtcp_port", attr->a_value); - - } else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) { - int crypto_tag; - - if (!(tech_pvt->profile->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) && - !switch_true(switch_channel_get_variable(tech_pvt->channel, "sip_allow_crypto_in_avp"))) { - if (m->m_proto != sdp_proto_srtp) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n"); - match = 0; - goto done; - } - } - - crypto = attr->a_value; - crypto_tag = atoi(crypto); - - got_video_crypto = switch_core_session_check_incoming_crypto(tech_pvt->session, - SOFIA_HAS_VIDEO_CRYPTO_VARIABLE, - SWITCH_MEDIA_TYPE_VIDEO, crypto, crypto_tag); - - } - } - - if (got_video_crypto && !got_video_avp) { - switch_channel_set_variable(tech_pvt->channel, SOFIA_CRYPTO_MANDATORY_VARIABLE, "true"); - switch_channel_set_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_VARIABLE, "true"); - } - - if (!(rm_encoding = map->rm_encoding)) { - rm_encoding = ""; - } - - for (i = 0; i < total_codecs; i++) { - const switch_codec_implementation_t *imp = codec_array[i]; - - if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) { - continue; - } - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n", - rm_encoding, map->rm_pt, imp->iananame, imp->ianacode); - if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { - vmatch = (map->rm_pt == imp->ianacode) ? 1 : 0; - } else { - vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1; - } - - - if (vmatch && (map->rm_rate == imp->samples_per_second)) { - mimp = imp; - break; - } else { - vmatch = 0; - } - } - - if (mimp) { - if ((tech_pvt->video_rm_encoding = switch_core_session_strdup(session, (char *) rm_encoding))) { - char tmp[50]; - const char *mirror = switch_channel_get_variable(tech_pvt->channel, "sip_mirror_remote_video_codec_payload"); - - tech_pvt->video_pt = (switch_payload_t) map->rm_pt; - tech_pvt->video_rm_rate = map->rm_rate; - tech_pvt->video_codec_ms = mimp->microseconds_per_packet / 1000; - tech_pvt->remote_sdp_video_ip = switch_core_session_strdup(session, (char *) connection->c_address); - tech_pvt->video_rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp); - tech_pvt->remote_sdp_video_port = (switch_port_t) m->m_port; - tech_pvt->video_agreed_pt = (switch_payload_t) map->rm_pt; - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_video_port); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_VIDEO_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_VIDEO_PORT_VARIABLE, tmp); - switch_channel_set_variable(tech_pvt->channel, "sip_video_fmtp", tech_pvt->video_rm_fmtp); - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->video_agreed_pt); - switch_channel_set_variable(tech_pvt->channel, "sip_video_pt", tmp); - sofia_media_check_video_codecs(tech_pvt); - - tech_pvt->video_recv_pt = (switch_payload_t)map->rm_pt; - - if (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - sofia_media_get_offered_pt(tech_pvt, mimp, &tech_pvt->video_recv_pt); - } - - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->video_recv_pt); - switch_channel_set_variable(tech_pvt->channel, "sip_video_recv_pt", tmp); - if (!match && vmatch) match = 1; - - break; - } else { - vmatch = 0; - } - } - } - } - } - - done: - - if (parser) { - sdp_parser_free(parser); - } - - tech_pvt->cng_pt = cng_pt; - sofia_set_flag_locked(tech_pvt, TFLAG_SDP); - - return match; -} -#endif - switch_status_t sofia_media_activate_rtp(private_object_t *tech_pvt) { - const char *err = NULL; - const char *val = NULL; - switch_rtp_flag_t flags[SWITCH_RTP_FLAG_INVALID] = {0}; - switch_status_t status = SWITCH_STATUS_SUCCESS; - char tmp[50]; - uint32_t rtp_timeout_sec = tech_pvt->profile->rtp_timeout_sec; - uint32_t rtp_hold_timeout_sec = tech_pvt->profile->rtp_hold_timeout_sec; - char *timer_name = NULL; - const char *var; - uint32_t delay = tech_pvt->profile->rtp_digit_delay; - - switch_assert(tech_pvt != NULL); - - if (switch_channel_down(tech_pvt->channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) { - return SWITCH_STATUS_FALSE; - } + int ok; switch_mutex_lock(tech_pvt->sofia_mutex); - - if (switch_rtp_ready(tech_pvt->rtp_session)) { - switch_rtp_reset_media_timer(tech_pvt->rtp_session); - } - - if ((var = switch_channel_get_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_VARIABLE)) && switch_true(var)) { - switch_channel_set_flag(tech_pvt->channel, CF_SECURE); - } - - if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) { - status = SWITCH_STATUS_SUCCESS; - goto end; - } - - - if (!sofia_test_flag(tech_pvt, TFLAG_REINVITE)) { - if (switch_rtp_ready(tech_pvt->rtp_session)) { - if (switch_channel_test_flag(tech_pvt->channel, CF_VIDEO_POSSIBLE) && !switch_rtp_ready(tech_pvt->video_rtp_session)) { - goto video; - } - - status = SWITCH_STATUS_SUCCESS; - goto end; - } - } - - if ((status = sofia_media_tech_set_codec(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) { - goto end; - } - - memset(flags, 0, sizeof(flags)); - flags[SWITCH_RTP_FLAG_DATAWAIT]++; - - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && - !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { - flags[SWITCH_RTP_FLAG_AUTOADJ]++; - } - - - if (sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_RFC2833) - || ((val = switch_channel_get_variable(tech_pvt->channel, "pass_rfc2833")) && switch_true(val))) { - sofia_set_flag(tech_pvt, TFLAG_PASS_RFC2833); - } - - - if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFLUSH) - || ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_autoflush")) && switch_true(val))) { - flags[SWITCH_RTP_FLAG_AUTOFLUSH]++; - } - - if (!(sofia_test_pflag(tech_pvt->profile, PFLAG_REWRITE_TIMESTAMPS) || - ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_rewrite_timestamps")) && switch_true(val)))) { - flags[SWITCH_RTP_FLAG_RAW_WRITE]++; - } - - if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG)) { - tech_pvt->cng_pt = 0; - } else if (tech_pvt->cng_pt) { - flags[SWITCH_RTP_FLAG_AUTO_CNG]++; - } - -#if __BYTE_ORDER == __LITTLE_ENDIAN - if (!strcasecmp(tech_pvt->read_impl.iananame, "L16")) { - flags[SWITCH_RTP_FLAG_BYTESWAP]++; - } -#endif - - if ((flags[SWITCH_RTP_FLAG_BYTESWAP]) && (val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_byteswap")) && switch_true(val)) { - flags[SWITCH_RTP_FLAG_BYTESWAP] = 0; - } - - if (tech_pvt->rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) { - //const char *ip = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE); - //const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE); - char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session); - switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session); - - if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n", - switch_channel_get_name(tech_pvt->channel)); - if (switch_rtp_ready(tech_pvt->rtp_session)) { - if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "%s Set audio receive payload in Re-INVITE for non-matching dynamic PT to %u\n", - switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt); - - switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "%s Setting audio receive payload in Re-INVITE to %u\n", - switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt); - switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->agreed_pt); - } - - } - goto video; - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n", - switch_channel_get_name(tech_pvt->channel), - remote_host, remote_port, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); - - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); - } - } - - if (!switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n", - switch_channel_get_name(tech_pvt->channel), - tech_pvt->local_sdp_audio_ip, - tech_pvt->local_sdp_audio_port, - tech_pvt->remote_sdp_audio_ip, - tech_pvt->remote_sdp_audio_port, tech_pvt->agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000); - - if (switch_rtp_ready(tech_pvt->rtp_session)) { - switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->agreed_pt); - - if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "%s Set audio receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt); - - switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt); - } else { - switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->agreed_pt); - } - - } - } - - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->local_sdp_audio_port); - switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->local_sdp_audio_ip); - switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, tmp); - switch_channel_set_variable(tech_pvt->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip); - - if (tech_pvt->rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) { - const char *rport = NULL; - switch_port_t remote_rtcp_port = 0; - - - - if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port"))) { - remote_rtcp_port = (switch_port_t)atoi(rport); - } - - if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port, - remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n", - tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && - !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { - /* Reactivate the NAT buster flag. */ - switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); - } - } - goto video; - } - - if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { - sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL); - - memset(flags, 0, sizeof(flags)); - flags[SWITCH_RTP_FLAG_DATAWAIT]++; - flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++; - - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && - !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { - flags[SWITCH_RTP_FLAG_AUTOADJ]++; - } - timer_name = NULL; - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n", - switch_channel_get_name(tech_pvt->channel), - tech_pvt->local_sdp_audio_ip, - tech_pvt->local_sdp_audio_port, - tech_pvt->remote_sdp_audio_ip, - tech_pvt->remote_sdp_audio_port, tech_pvt->agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000); - - if (switch_rtp_ready(tech_pvt->rtp_session)) { - switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->agreed_pt); - } - - } else { - timer_name = tech_pvt->profile->timer_name; - - if ((var = switch_channel_get_variable(tech_pvt->channel, "rtp_timer_name"))) { - timer_name = (char *) var; - } - } - - if (switch_channel_up(tech_pvt->channel) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) { - tech_pvt->rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip, - tech_pvt->local_sdp_audio_port, - tech_pvt->remote_sdp_audio_ip, - tech_pvt->remote_sdp_audio_port, - tech_pvt->agreed_pt, - tech_pvt->read_impl.samples_per_packet, - tech_pvt->codec_ms * 1000, - flags, timer_name, &err, switch_core_session_get_pool(tech_pvt->session)); - } - - if (switch_rtp_ready(tech_pvt->rtp_session)) { - uint8_t vad_in = sofia_test_flag(tech_pvt, TFLAG_VAD_IN) ? 1 : 0; - uint8_t vad_out = sofia_test_flag(tech_pvt, TFLAG_VAD_OUT) ? 1 : 0; - uint8_t inb = sofia_test_flag(tech_pvt, TFLAG_OUTBOUND) ? 0 : 1; - uint32_t stun_ping = 0; - const char *ssrc; - - switch_core_media_set_rtp_session(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, tech_pvt->rtp_session); - - - if ((ssrc = switch_channel_get_variable(tech_pvt->channel, "rtp_use_ssrc"))) { - uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10); - switch_rtp_set_ssrc(tech_pvt->rtp_session, ssrc_ul); - } - - - switch_channel_set_flag(tech_pvt->channel, CF_FS_RTP); - - switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_pt", "%d", tech_pvt->agreed_pt); - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_enable_vad_in")) && switch_true(val)) { - vad_in = 1; - } - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_enable_vad_out")) && switch_true(val)) { - vad_out = 1; - } - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_vad_in")) && switch_true(val)) { - vad_in = 0; - } - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_vad_out")) && switch_true(val)) { - vad_out = 0; - } - - if ((tech_pvt->stun_flags & STUN_FLAG_SET) && (val = switch_channel_get_variable(tech_pvt->channel, "rtp_stun_ping"))) { - int ival = atoi(val); - - if (ival <= 0) { - if (switch_true(val)) { - ival = 6; - } - } - - stun_ping = (ival * tech_pvt->read_impl.samples_per_second) / tech_pvt->read_impl.samples_per_packet; - } - - tech_pvt->ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session); - switch_channel_set_variable_printf(tech_pvt->channel, "rtp_use_ssrc", "%u", tech_pvt->ssrc); - - sofia_set_flag(tech_pvt, TFLAG_RTP); - sofia_set_flag(tech_pvt, TFLAG_IO); - - if (tech_pvt->profile->auto_rtp_bugs & RTP_BUG_IGNORE_MARK_BIT) { - tech_pvt->rtp_bugs |= RTP_BUG_IGNORE_MARK_BIT; - } - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_manual_rtp_bugs"))) { - switch_core_media_parse_rtp_bugs(&tech_pvt->rtp_bugs, val); - } - - switch_rtp_intentional_bugs(tech_pvt->rtp_session, tech_pvt->rtp_bugs | tech_pvt->profile->manual_rtp_bugs); - - if ((vad_in && inb) || (vad_out && !inb)) { - switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING | SWITCH_VAD_FLAG_EVENTS_TALK | SWITCH_VAD_FLAG_EVENTS_NOTALK); - sofia_set_flag(tech_pvt, TFLAG_VAD); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n", - switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : ""); - } - - if (stun_ping) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Setting stun ping to %s:%d\n", tech_pvt->stun_ip, - stun_ping); - switch_rtp_activate_stun_ping(tech_pvt->rtp_session, tech_pvt->stun_ip, tech_pvt->stun_port, stun_ping, - (tech_pvt->stun_flags & STUN_FLAG_FUNNY) ? 1 : 0); - } - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtcp_audio_interval_msec")) || (val = tech_pvt->profile->rtcp_audio_interval_msec)) { - const char *rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port"); - switch_port_t remote_port = 0; - if (rport) { - remote_port = (switch_port_t)atoi(rport); - } - if (!strcasecmp(val, "passthru")) { - switch_rtp_activate_rtcp(tech_pvt->rtp_session, -1, remote_port); - } else { - int interval = atoi(val); - if (interval < 100 || interval > 5000) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, - "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval); - } else { - switch_rtp_activate_rtcp(tech_pvt->rtp_session, interval, remote_port); - } - } - } - - if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec")) || (val = tech_pvt->profile->jb_msec)) { - int jb_msec = atoi(val); - int maxlen = 0, max_drift = 0; - char *p, *q; - - if ((p = strchr(val, ':'))) { - p++; - maxlen = atoi(p); - if ((q = strchr(p, ':'))) { - q++; - max_drift = abs(atoi(q)); - } - } - - if (jb_msec < 20 || jb_msec > 10000) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, - "Invalid Jitterbuffer spec [%d] must be between 20 and 10000\n", jb_msec); - } else { - int qlen, maxqlen = 50; - - qlen = jb_msec / (tech_pvt->read_impl.microseconds_per_packet / 1000); - - if (qlen < 1) { - qlen = 3; - } - - if (maxlen) { - maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000); - } - - if (maxqlen < qlen) { - maxqlen = qlen * 5; - } - if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen, - tech_pvt->read_impl.samples_per_packet, - tech_pvt->read_impl.samples_per_second, max_drift) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), - SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen); - switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER); - if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) { - switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC); - } - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), - SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen); - } - - } - } - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_timeout_sec"))) { - int v = atoi(val); - if (v >= 0) { - rtp_timeout_sec = v; - } - } - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_hold_timeout_sec"))) { - int v = atoi(val); - if (v >= 0) { - rtp_hold_timeout_sec = v; - } - } - - if (rtp_timeout_sec) { - tech_pvt->max_missed_packets = (tech_pvt->read_impl.samples_per_second * rtp_timeout_sec) / tech_pvt->read_impl.samples_per_packet; - - switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets); - if (!rtp_hold_timeout_sec) { - rtp_hold_timeout_sec = rtp_timeout_sec * 10; - } - } - - if (rtp_hold_timeout_sec) { - tech_pvt->max_missed_hold_packets = (tech_pvt->read_impl.samples_per_second * rtp_hold_timeout_sec) / tech_pvt->read_impl.samples_per_packet; - } - - if (tech_pvt->te) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send payload to %u\n", tech_pvt->te); - switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te); - switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", tech_pvt->te); - } - - if (tech_pvt->recv_te) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set 2833 dtmf receive payload to %u\n", tech_pvt->recv_te); - switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, tech_pvt->recv_te); - switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_recv_payload", "%d", tech_pvt->recv_te); - } - - if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "%s Set audio receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt); - - switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt); - } - - if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) || - ((val = switch_channel_get_variable(tech_pvt->channel, "supress_cng")) && switch_true(val)) || - ((val = switch_channel_get_variable(tech_pvt->channel, "suppress_cng")) && switch_true(val))) { - tech_pvt->cng_pt = 0; - } - - if (((val = switch_channel_get_variable(tech_pvt->channel, "rtp_digit_delay")))) { - int delayi = atoi(val); - if (delayi < 0) delayi = 0; - delay = (uint32_t) delayi; - } - - - if (delay) { - switch_rtp_set_interdigit_delay(tech_pvt->rtp_session, delay); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "%s Set rtp dtmf delay to %u\n", switch_channel_get_name(tech_pvt->channel), delay); - - } - - if (tech_pvt->cng_pt && !sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", tech_pvt->cng_pt); - switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt); - } - - switch_core_session_apply_crypto(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, SOFIA_SECURE_MEDIA_CONFIRMED_VARIABLE); - - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip); - switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); - - - if (switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASSTHRU)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_INFO, "Activating ZRTP PROXY MODE\n"); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Disable NOTIMER_DURING_BRIDGE\n"); - sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Activating audio UDPTL mode\n"); - switch_rtp_udptl_mode(tech_pvt->rtp_session); - } - - - video: - - sofia_media_check_video_codecs(tech_pvt); - - if (switch_channel_test_flag(tech_pvt->channel, CF_VIDEO_POSSIBLE) && tech_pvt->video_rm_encoding && tech_pvt->remote_sdp_video_port) { - /******************************************************************************************/ - if (tech_pvt->video_rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) { - //const char *ip = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE); - //const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE); - char *remote_host = switch_rtp_get_remote_host(tech_pvt->video_rtp_session); - switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->video_rtp_session); - - - - if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_video_ip) && remote_port == tech_pvt->remote_sdp_video_port) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Video params are unchanged for %s.\n", - switch_channel_get_name(tech_pvt->channel)); - goto video_up; - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Video params changed for %s from %s:%d to %s:%d\n", - switch_channel_get_name(tech_pvt->channel), - remote_host, remote_port, tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port); - } - } - - if (!switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "VIDEO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n", switch_channel_get_name(tech_pvt->channel), - tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_video_port, tech_pvt->remote_sdp_video_ip, - tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000); - - if (switch_rtp_ready(tech_pvt->video_rtp_session)) { - switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt); - } - } - - switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->local_sdp_video_port); - switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip); - switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, tmp); - - - if (tech_pvt->video_rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) { - const char *rport = NULL; - switch_port_t remote_rtcp_port = 0; - - sofia_clear_flag_locked(tech_pvt, TFLAG_REINVITE); - - if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_video_rtcp_port"))) { - remote_rtcp_port = (switch_port_t)atoi(rport); - } - - if (switch_rtp_set_remote_address - (tech_pvt->video_rtp_session, tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port, remote_rtcp_port, SWITCH_TRUE, - &err) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n", - tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port); - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && - !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { - /* Reactivate the NAT buster flag. */ - switch_rtp_set_flag(tech_pvt->video_rtp_session, SWITCH_RTP_FLAG_AUTOADJ); - } - - } - goto video_up; - } - - if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { - sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL); - - memset(flags, 0, sizeof(flags)); - flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++; - flags[SWITCH_RTP_FLAG_DATAWAIT]++; - - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && - !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { - flags[SWITCH_RTP_FLAG_AUTOADJ]++; - } - timer_name = NULL; - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "PROXY VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n", - switch_channel_get_name(tech_pvt->channel), - tech_pvt->local_sdp_audio_ip, - tech_pvt->local_sdp_video_port, - tech_pvt->remote_sdp_video_ip, - tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000); - - if (switch_rtp_ready(tech_pvt->video_rtp_session)) { - switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt); - } - } else { - timer_name = tech_pvt->profile->timer_name; - - if ((var = switch_channel_get_variable(tech_pvt->channel, "rtp_timer_name"))) { - timer_name = (char *) var; - } - } - - /******************************************************************************************/ - - if (tech_pvt->video_rtp_session) { - goto video_up; - } - - - if (!tech_pvt->local_sdp_video_port) { - sofia_glue_tech_choose_video_port(tech_pvt, 1); - } - - memset(flags, 0, sizeof(flags)); - flags[SWITCH_RTP_FLAG_DATAWAIT]++; - flags[SWITCH_RTP_FLAG_RAW_WRITE]++; - - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && - !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { - flags[SWITCH_RTP_FLAG_AUTOADJ]++; - } - - if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { - flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++; - } - sofia_media_tech_set_video_codec(tech_pvt, 0); - - flags[SWITCH_RTP_FLAG_USE_TIMER] = 0; - flags[SWITCH_RTP_FLAG_NOBLOCK] = 0; - flags[SWITCH_RTP_FLAG_VIDEO]++; - - tech_pvt->video_rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip, - tech_pvt->local_sdp_video_port, - tech_pvt->remote_sdp_video_ip, - tech_pvt->remote_sdp_video_port, - tech_pvt->video_agreed_pt, - 1, 90000, flags, NULL, &err, switch_core_session_get_pool(tech_pvt->session)); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n", - switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) ? "PROXY " : "", - switch_channel_get_name(tech_pvt->channel), - tech_pvt->local_sdp_audio_ip, - tech_pvt->local_sdp_video_port, - tech_pvt->remote_sdp_video_ip, - tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt, - 0, switch_rtp_ready(tech_pvt->video_rtp_session) ? "SUCCESS" : err); - - - if (switch_rtp_ready(tech_pvt->video_rtp_session)) { - switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt); - switch_core_media_set_rtp_session(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO, tech_pvt->video_rtp_session); - } - - if (switch_rtp_ready(tech_pvt->video_rtp_session)) { - const char *ssrc; - switch_channel_set_flag(tech_pvt->channel, CF_VIDEO); - if ((ssrc = switch_channel_get_variable(tech_pvt->channel, "rtp_use_video_ssrc"))) { - uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10); - switch_rtp_set_ssrc(tech_pvt->video_rtp_session, ssrc_ul); - } - - - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_manual_video_rtp_bugs"))) { - switch_core_media_parse_rtp_bugs(&tech_pvt->video_rtp_bugs, val); - } - - switch_rtp_intentional_bugs(tech_pvt->video_rtp_session, tech_pvt->video_rtp_bugs | tech_pvt->profile->manual_video_rtp_bugs); - - if (tech_pvt->video_recv_pt != tech_pvt->video_agreed_pt) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "%s Set video receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->video_recv_pt); - switch_rtp_set_recv_pt(tech_pvt->video_rtp_session, tech_pvt->video_recv_pt); - } - - switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_pt", "%d", tech_pvt->video_agreed_pt); - tech_pvt->video_ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session); - switch_channel_set_variable_printf(tech_pvt->channel, "rtp_use_video_ssrc", "%u", tech_pvt->ssrc); - - switch_core_session_apply_crypto(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO, SOFIA_SECURE_VIDEO_CONFIRMED_VARIABLE); - - - if ((val = switch_channel_get_variable(tech_pvt->channel, "rtcp_audio_interval_msec")) - || (val = tech_pvt->profile->rtcp_audio_interval_msec)) { - const char *rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_video_rtcp_port"); - switch_port_t remote_port = 0; - if (rport) { - remote_port = (switch_port_t)atoi(rport); - } - if (!strcasecmp(val, "passthru")) { - switch_rtp_activate_rtcp(tech_pvt->rtp_session, -1, remote_port); - } else { - int interval = atoi(val); - if (interval < 100 || interval > 5000) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, - "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval); - } else { - switch_rtp_activate_rtcp(tech_pvt->rtp_session, interval, remote_port); - } - } - } - if (switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASSTHRU)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Activating video UDPTL mode\n"); - switch_rtp_udptl_mode(tech_pvt->video_rtp_session); - } - - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err)); - switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - goto end; - } - } - - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err)); - switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - sofia_clear_flag_locked(tech_pvt, TFLAG_IO); - status = SWITCH_STATUS_FALSE; - goto end; - } - - video_up: - - sofia_set_flag(tech_pvt, TFLAG_IO); - status = SWITCH_STATUS_SUCCESS; - - end: - - sofia_clear_flag_locked(tech_pvt, TFLAG_REINVITE); - switch_core_recovery_track(tech_pvt->session); - switch_mutex_unlock(tech_pvt->sofia_mutex); - return status; + if (ok) { + sofia_set_flag(tech_pvt, TFLAG_RTP); + sofia_set_flag(tech_pvt, TFLAG_IO); + } } @@ -2419,7 +986,7 @@ void sofia_media_set_local_sdp(private_object_t *tech_pvt, const char *ip, switc /*****************************/ if (tech_pvt->video_rm_encoding) { - sofia_media_tech_set_video_codec(tech_pvt, 0); + 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; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 18c93e19c5..62b5f10b21 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -40,24 +40,9 @@ #include - #define MAX_CODEC_CHECK_FRAMES 50//x:mod_sofia.h #define MAX_MISMATCH_FRAMES 5//x:mod_sofia.h -typedef union { - int32_t intval; - uint32_t uintval; - char *charval; -} scm_multi_t; - - -static scm_type_t typemap[SCM_MAX] = { - /*SCM_INBOUND_CODEC_STRING*/ STYPE_CHARVAL, - /*SCM_OUTBOUND_CODEC_STRING*/ STYPE_CHARVAL, - /*SCM_AUTO_RTP_BUGS */ STYPE_INTVAL, - /*SCM_MANUAL_RTP_BUGS*/ STYPE_INTVAL -}; - typedef enum { SMH_INIT = (1 << 0), SMH_READY = (1 << 1) @@ -82,12 +67,26 @@ typedef struct codec_params_s {//x:tmp unsigned long rm_rate; uint32_t codec_ms; uint32_t bitrate; - char *remote_sdp_ip; + char *rm_fmtp; - switch_port_t remote_sdp_port; + switch_payload_t agreed_pt; switch_payload_t recv_pt; char *fmtp_out; + + + char *remote_sdp_ip; + switch_port_t remote_sdp_port; + + char *local_sdp_ip; + switch_port_t local_sdp_port; + + char *adv_sdp_ip; + switch_port_t adv_sdp_port; + char *proxy_sdp_ip; + switch_port_t proxy_sdp_port; + + } codec_params_t; @@ -111,8 +110,9 @@ typedef struct switch_rtp_engine_s { uint8_t codec_reinvites;//x:tp uint32_t max_missed_packets;//x:tp uint32_t max_missed_hold_packets;//x:tp + uint32_t ssrc; - + switch_rtp_bug_flag_t rtp_bugs; /** ZRTP **/ char *local_sdp_zrtp_hash; @@ -120,7 +120,7 @@ typedef struct switch_rtp_engine_s { codec_params_t codec_params; - + uint32_t timestamp_send; } switch_rtp_engine_t; @@ -128,11 +128,10 @@ typedef struct switch_rtp_engine_s { struct switch_media_handle_s { switch_core_session_t *session; switch_channel_t *channel; - switch_core_media_NDLB_t ndlb; switch_core_media_flag_t media_flags[SCMF_MAX]; smh_flag_t flags; switch_rtp_engine_t engines[SWITCH_MEDIA_TYPE_TOTAL]; - scm_multi_t params[SCM_MAX]; + char *codec_order[SWITCH_MAX_CODECS];//x:tp int codec_order_last;//x:tp const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS];//x:tp @@ -147,62 +146,11 @@ struct switch_media_handle_s { const switch_codec_implementation_t *negotiated_codecs[SWITCH_MAX_CODECS];//x:tp int num_negotiated_codecs;//x:tp switch_payload_t ianacodes[SWITCH_MAX_CODECS];//x:tp - int video_count;//x:tmp + int video_count;//x:tp + switch_core_media_params_t *mparams; }; -SWITCH_DECLARE(void) switch_media_set_param(switch_media_handle_t *smh, scm_param_t param, ...) -{ - scm_multi_t *val = &smh->params[param]; - scm_type_t type = typemap[param]; - va_list ap; - - va_start(ap, param); - - switch(type) { - case STYPE_INTVAL: - val->intval = va_arg(ap, int); - break; - case STYPE_UINTVAL: - val->uintval = va_arg(ap, unsigned int); - break; - case STYPE_CHARVAL: - val->charval = switch_core_session_strdup(smh->session, va_arg(ap, char *)); - break; - default: - abort(); - } - - va_end(ap); -} - -SWITCH_DECLARE(void *) switch_media_get_param(switch_media_handle_t *smh, scm_param_t param) -{ - scm_multi_t *val = &smh->params[param]; - scm_type_t type = typemap[param]; - - switch(type) { - case STYPE_INTVAL: - return &val->intval; - break; - case STYPE_UINTVAL: - return &val->uintval; - break; - case STYPE_CHARVAL: - return val->charval; - break; - default: - abort(); - } - - return NULL; - -} - -#define get_str(_o, _p) _o->params[_p].charval - - - static void _switch_core_media_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session, switch_media_type_t type) { switch_rtp_engine_t *aleg_engine; @@ -400,12 +348,12 @@ SWITCH_DECLARE(switch_t38_options_t *) switch_core_media_extract_t38_options(swi switch_t38_options_t *t38_options = NULL; if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) { - return 0; + return NULL; } if (!(sdp = sdp_session(parser))) { sdp_parser_free(parser); - return 0; + return NULL; } //switch_assert(tech_pvt != NULL); @@ -443,12 +391,12 @@ SWITCH_DECLARE(const char *)switch_core_media_get_codec_string(switch_core_sessi if (!preferred) { if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - preferred = get_str(smh, SCM_OUTBOUND_CODEC_STRING); - fallback = get_str(smh, SCM_INBOUND_CODEC_STRING); + preferred = smh->mparams->outbound_codec_string; + fallback = smh->mparams->inbound_codec_string; } else { - preferred = get_str(smh, SCM_INBOUND_CODEC_STRING); - fallback = get_str(smh, SCM_OUTBOUND_CODEC_STRING); + preferred = smh->mparams->inbound_codec_string; + fallback = smh->mparams->outbound_codec_string; } } } @@ -604,7 +552,7 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh ssec->local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, type_str, b64_key); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Set Local Key [%s]\n", ssec->local_crypto_key); - if (!(smh->ndlb & SM_NDLB_DISABLE_SRTP_AUTH) && + if (!(smh->mparams->ndlb & SM_NDLB_DISABLE_SRTP_AUTH) && !((val = switch_channel_get_variable(channel, "NDLB_support_asterisk_missing_srtp_auth")) && switch_true(val))) { ssec->crypto_type = type; } else { @@ -819,7 +767,7 @@ SWITCH_DECLARE(void) switch_core_session_check_outgoing_crypto(switch_core_sessi } -SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t **smhp, switch_core_session_t *session) +SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t **smhp, switch_core_session_t *session, switch_core_media_params_t *params) { switch_status_t status = SWITCH_STATUS_FALSE; switch_media_handle_t *smh = NULL; @@ -833,7 +781,7 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t session->media_handle->media_flags[SCMF_RUNNING] = 1; session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN; session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN; - + session->media_handle->mparams = params; status = SWITCH_STATUS_SUCCESS; } @@ -841,27 +789,6 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t return status; } -SWITCH_DECLARE(void) switch_media_handle_set_ndlb(switch_media_handle_t *smh, switch_core_media_NDLB_t flag) -{ - switch_assert(smh); - - smh->ndlb |= flag; - -} - -SWITCH_DECLARE(void) switch_media_handle_clear_ndlb(switch_media_handle_t *smh, switch_core_media_NDLB_t flag) -{ - switch_assert(smh); - - smh->ndlb &= ~flag; -} - -SWITCH_DECLARE(int32_t) switch_media_handle_test_ndlb(switch_media_handle_t *smh, switch_core_media_NDLB_t flag) -{ - switch_assert(smh); - return (smh->ndlb & flag); -} - SWITCH_DECLARE(void) switch_media_handle_set_media_flag(switch_media_handle_t *smh, switch_core_media_flag_t flag) { switch_assert(smh); @@ -991,9 +918,9 @@ SWITCH_DECLARE(void) switch_core_media_prepare_codecs(switch_core_session_t *ses } - -SWITCH_DECLARE(switch_status_t) switch_core_session_read_media_frame(switch_core_session_t *session, switch_frame_t **frame, - switch_io_flag_t flags, int stream_id, switch_media_type_t type) +//? +SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session_t *session, switch_frame_t **frame, + switch_io_flag_t flags, int stream_id, switch_media_type_t type) { switch_rtcp_frame_t rtcp_frame; switch_rtp_engine_t *engine; @@ -1028,14 +955,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_media_frame(switch_core if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { if (status == SWITCH_STATUS_TIMEOUT) { -#if 0 - if (sofia_test_flag(engine, TFLAG_SIP_HOLD)) { - switch_core_media_toggle_hold(engine, 0); - sofia_clear_flag_locked(engine, TFLAG_SIP_HOLD); - switch_channel_clear_flag(channel, CF_LEG_HOLDING); - } -#endif - if (switch_channel_get_variable(session->channel, "execute_on_media_timeout")) { *frame = &engine->read_frame; switch_set_flag((*frame), SFF_CNG); @@ -1199,12 +1118,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_media_frame(switch_core engine->codec_ms = codec_ms; } -#if fixmeXXXXX - if (switch_core_media_tech_set_codec(engine, 2) != SWITCH_STATUS_SUCCESS) { + + if (switch_core_media_set_codec(session, 2, 0) != SWITCH_STATUS_SUCCESS) { *frame = NULL; return SWITCH_STATUS_GENERR; } -#endif + if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) { int v = atoi(val); if (v >= 0) { @@ -1283,7 +1202,65 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_media_frame(switch_core return SWITCH_STATUS_SUCCESS; } +//? +SWITCH_DECLARE(switch_status_t) switch_core_media_write_frame(switch_core_session_t *session, + switch_frame_t *frame, switch_io_flag_t flags, int stream_id, switch_media_type_t type) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + int bytes = 0, samples = 0, frames = 0; + switch_rtp_engine_t *engine; + switch_media_handle_t *smh; + if (!(smh = session->media_handle)) { + return SWITCH_STATUS_FALSE; + } + + if (!(smh->flags & SCMF_RUNNING)) { + return SWITCH_STATUS_FALSE; + } + + engine = &smh->engines[type]; + + + while (!(engine->read_codec.implementation && switch_rtp_ready(engine->rtp_session))) { + if (switch_channel_ready(session->channel)) { + switch_yield(10000); + } else { + return SWITCH_STATUS_GENERR; + } + } + + if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) { + return SWITCH_STATUS_GENERR; + } + + + if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) { + return SWITCH_STATUS_FALSE; + } + + if (!switch_test_flag(frame, SFF_CNG) && !switch_test_flag(frame, SFF_PROXY_PACKET)) { + if (engine->read_impl.encoded_bytes_per_packet) { + bytes = engine->read_impl.encoded_bytes_per_packet; + frames = ((int) frame->datalen / bytes); + } else + frames = 1; + + samples = frames * engine->read_impl.samples_per_packet; + } + + engine->timestamp_send += samples; + + if (!switch_rtp_write_frame(engine->rtp_session, frame)) { + status = SWITCH_STATUS_FALSE; + } + + + return status; +} + + +//? SWITCH_DECLARE(void) switch_core_media_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); @@ -1312,7 +1289,7 @@ SWITCH_DECLARE(void) switch_core_media_copy_t38_options(switch_t38_options_t *t3 } - +//? SWITCH_DECLARE(switch_status_t) switch_core_media_get_offered_pt(switch_core_session_t *session, const switch_codec_implementation_t *mimp, switch_payload_t *pt) { int i = 0; @@ -1336,8 +1313,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_get_offered_pt(switch_core_ses return SWITCH_STATUS_FALSE; } + + //? -switch_status_t switch_core_media_set_video_codec(switch_core_session_t *session, int force) +SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_session_t *session, int force) { switch_media_handle_t *smh; switch_rtp_engine_t *v_engine; @@ -1442,7 +1421,7 @@ switch_status_t switch_core_media_set_video_codec(switch_core_session_t *session //? -switch_status_t switch_core_media_set_codec(switch_core_session_t *session, int force, uint32_t codec_flags) +SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_t *session, int force, uint32_t codec_flags) { switch_status_t status = SWITCH_STATUS_SUCCESS; int resetting = 0; @@ -1587,7 +1566,7 @@ switch_status_t switch_core_media_set_codec(switch_core_session_t *session, int } //? -void switch_core_media_check_video_codecs(switch_core_session_t *session) +SWITCH_DECLARE(void) switch_core_media_check_video_codecs(switch_core_session_t *session) { switch_media_handle_t *smh; @@ -1683,17 +1662,17 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s if ((smh->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) { - if ((smh->params[SCM_AUTO_RTP_BUGS].intval & RTP_BUG_CISCO_SKIP_MARK_BIT_2833)) { + if ((smh->mparams->auto_rtp_bugs & RTP_BUG_CISCO_SKIP_MARK_BIT_2833)) { if (strstr(smh->origin, "CiscoSystemsSIP-GW-UserAgent")) { - smh->params[SCM_MANUAL_RTP_BUGS].intval |= RTP_BUG_CISCO_SKIP_MARK_BIT_2833; + a_engine->rtp_bugs |= RTP_BUG_CISCO_SKIP_MARK_BIT_2833; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n"); } } - if ((smh->params[SCM_AUTO_RTP_BUGS].intval & RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833)) { + if ((smh->mparams->auto_rtp_bugs & RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833)) { if (strstr(smh->origin, "Sonus_UAC")) { - smh->params[SCM_MANUAL_RTP_BUGS].intval |= RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833; + a_engine->rtp_bugs |= RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Hello,\nI see you have a Sonus!\n" "FYI, Sonus cannot follow the RFC on the proper way to send DTMF.\n" @@ -1927,7 +1906,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) { int crypto_tag; - if (!(smh->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) && + if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) && !switch_true(switch_channel_get_variable(session->channel, "sip_allow_crypto_in_avp"))) { if (m->m_proto != sdp_proto_srtp) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n"); @@ -1976,7 +1955,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } for (map = m->m_rtpmaps; map; map = map->rm_next) { - if ((zstr(map->rm_encoding) || (smh->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { + if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { match = (map->rm_pt == a_engine->codec_params.pt) ? 1 : 0; } else { match = strcasecmp(switch_str_nil(map->rm_encoding), a_engine->codec_params.iananame) ? 0 : 1; @@ -2088,7 +2067,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u]/[%s:%d:%u:%d:%u]\n", rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms, map_bit_rate, imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate); - if ((zstr(map->rm_encoding) || (smh->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { + if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { match = (map->rm_pt == imp->ianacode) ? 1 : 0; } else { match = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1; @@ -2273,7 +2252,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) { int crypto_tag; - if (!(smh->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) && + if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) && !switch_true(switch_channel_get_variable(session->channel, "sip_allow_crypto_in_avp"))) { if (m->m_proto != sdp_proto_srtp) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n"); @@ -2310,7 +2289,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n", rm_encoding, map->rm_pt, imp->iananame, imp->ianacode); - if ((zstr(map->rm_encoding) || (smh->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { + if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { vmatch = (map->rm_pt == imp->ianacode) ? 1 : 0; } else { vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1; @@ -2478,6 +2457,1041 @@ SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session } +//? +#define RA_PTR_LEN 512 +SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_session_t *session, const char *sdp_str) +{ + const char *err; + char rip[RA_PTR_LEN] = ""; + char rp[RA_PTR_LEN] = ""; + char rvp[RA_PTR_LEN] = ""; + char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL, *pe; + int x; + const char *val; + switch_status_t status = SWITCH_STATUS_FALSE; + switch_rtp_engine_t *a_engine, *v_engine; + switch_media_handle_t *smh; + + 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]; + + if (zstr(sdp_str)) { + sdp_str = smh->mparams->remote_sdp_str; + } + + if (zstr(sdp_str)) { + goto end; + } + + if ((p = (char *) switch_stristr("c=IN IP4 ", sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", sdp_str))) { + ip_ptr = p + 9; + } + + if ((p = (char *) switch_stristr("m=audio ", sdp_str))) { + port_ptr = p + 8; + } + + if ((p = (char *) switch_stristr("m=image ", sdp_str))) { + char *tmp = p + 8; + + if (tmp && atoi(tmp)) { + port_ptr = tmp; + } + } + + if ((p = (char *) switch_stristr("m=video ", sdp_str))) { + vid_port_ptr = p + 8; + } + + if (!(ip_ptr && port_ptr)) { + goto end; + } + + p = ip_ptr; + pe = p + strlen(p); + x = 0; + while (x < sizeof(rip) - 1 && p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F'))) { + rip[x++] = *p; + p++; + if (p >= pe) { + goto end; + } + } + + p = port_ptr; + x = 0; + while (x < sizeof(rp) - 1 && p && *p && (*p >= '0' && *p <= '9')) { + rp[x++] = *p; + p++; + if (p >= pe) { + goto end; + } + } + + p = vid_port_ptr; + x = 0; + while (x < sizeof(rvp) - 1 && p && *p && (*p >= '0' && *p <= '9')) { + rvp[x++] = *p; + p++; + if (p >= pe) { + goto end; + } + } + + if (!(*rip && *rp)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "invalid SDP\n"); + goto end; + } + + a_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, rip); + a_engine->codec_params.remote_sdp_port = (switch_port_t) atoi(rp); + + if (*rvp) { + v_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, rip); + v_engine->codec_params.remote_sdp_port = (switch_port_t) atoi(rvp); + } + + if (v_engine->codec_params.remote_sdp_ip && v_engine->codec_params.remote_sdp_port) { + if (!strcmp(v_engine->codec_params.remote_sdp_ip, rip) && atoi(rvp) == v_engine->codec_params.remote_sdp_port) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote video address:port [%s:%d] has not changed.\n", + v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port); + } else { + switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE); + switch_channel_set_flag(session->channel, CF_VIDEO); + if (switch_rtp_ready(v_engine->rtp_session)) { + const char *rport = NULL; + switch_port_t remote_rtcp_port = 0; + + if ((rport = switch_channel_get_variable(session->channel, "sip_remote_video_rtcp_port"))) { + remote_rtcp_port = (switch_port_t)atoi(rport); + } + + + if (switch_rtp_set_remote_address(v_engine->rtp_session, v_engine->codec_params.remote_sdp_ip, + v_engine->codec_params.remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n", + v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port); + if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(session->channel, CF_PROXY_MODE) && + !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { + /* Reactivate the NAT buster flag. */ + switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); + } + if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING)) { + v_engine->check_frames = 0; + } + } + } + } + } + + if (switch_rtp_ready(a_engine->rtp_session)) { + char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session); + switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session); + const char *rport = NULL; + switch_port_t remote_rtcp_port = 0; + + 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, "Remote address:port [%s:%d] has not changed.\n", + a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port); + switch_goto_status(SWITCH_STATUS_BREAK, end); + } + + if ((rport = switch_channel_get_variable(session->channel, "sip_remote_audio_rtcp_port"))) { + remote_rtcp_port = (switch_port_t)atoi(rport); + } + + + if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->codec_params.remote_sdp_ip, + a_engine->codec_params.remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err); + status = SWITCH_STATUS_GENERR; + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n", + a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port); + if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && + !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { + /* Reactivate the NAT buster flag. */ + switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); + } + if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING)) { + a_engine->check_frames = 0; + } + status = SWITCH_STATUS_SUCCESS; + } + } + + end: + + return status; +} + +//? +SWITCH_DECLARE(int) switch_core_media_check_nat(switch_media_handle_t *smh, const char *network_ip) +{ + switch_assert(network_ip); + + return (smh->mparams->extsipip && + !switch_check_network_list_ip(network_ip, "loopback.auto") && + !switch_check_network_list_ip(network_ip, smh->mparams->local_network)); +} + +//? +SWITCH_DECLARE(switch_status_t) sofia_glue_ext_address_lookup(switch_core_session_t *session, char **ip, switch_port_t *port, const char *sourceip) + +{ + char *error = ""; + switch_status_t status = SWITCH_STATUS_FALSE; + int x; + switch_port_t myport = *port; + switch_port_t stun_port = SWITCH_STUN_DEFAULT_PORT; + char *stun_ip = NULL; + switch_media_handle_t *smh; + switch_memory_pool_t *pool = switch_core_session_get_pool(session); + + if (!(smh = session->media_handle)) { + return SWITCH_STATUS_FALSE; + } + + if (!sourceip) { + return status; + } + + if (!strncasecmp(sourceip, "host:", 5)) { + status = (*ip = switch_stun_host_lookup(sourceip + 5, pool)) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; + } else if (!strncasecmp(sourceip, "stun:", 5)) { + char *p; + + stun_ip = strdup(sourceip + 5); + + if ((p = strchr(stun_ip, ':'))) { + int iport; + *p++ = '\0'; + iport = atoi(p); + if (iport > 0 && iport < 0xFFFF) { + stun_port = (switch_port_t) iport; + } + } + + if (zstr(stun_ip)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! NO STUN SERVER\n"); + goto out; + } + + for (x = 0; x < 5; x++) { + if ((status = switch_stun_lookup(ip, port, stun_ip, stun_port, &error, pool)) != SWITCH_STATUS_SUCCESS) { + switch_yield(100000); + } else { + break; + } + } + if (status != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! %s:%d [%s]\n", stun_ip, stun_port, error); + goto out; + } + if (!*ip) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! No IP returned\n"); + goto out; + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Success [%s]:[%d]\n", *ip, *port); + status = SWITCH_STATUS_SUCCESS; + + if (myport == *port && !strcmp(*ip, smh->mparams->rtpip)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Not Required ip and port match. [%s]:[%d]\n", *ip, *port); + } else { + smh->mparams->stun_ip = switch_core_session_strdup(session, stun_ip); + smh->mparams->stun_port = stun_port; + smh->mparams->stun_flags |= STUN_FLAG_SET; + } + } else { + *ip = (char *) sourceip; + status = SWITCH_STATUS_SUCCESS; + } + + out: + + switch_safe_free(stun_ip); + + return status; +} + + + + +//? +SWITCH_DECLARE(switch_status_t) switch_core_media_choose_video_port(switch_core_session_t *session, 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_media_handle_t *smh; + + 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]; + + 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) { + 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); + } + + /* 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"); + return SWITCH_STATUS_FALSE; + } + + sdp_port = v_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); + + /* Find an IP address to use */ + if (!(use_ip = switch_channel_get_variable(session->channel, "rtp_adv_video_ip")) + && !zstr(smh->mparams->extrtpip)) { + use_ip = smh->mparams->extrtpip; + } + + if (use_ip) { + if (sofia_glue_ext_address_lookup(session, &lookup_rtpip, &sdp_port, use_ip) != 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 = smh->mparams->rtpip; + } + } else { + /* No NAT traversal required, use the profile's rtp ip */ + 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); + switch_channel_set_variable_printf(session->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, "%d", sdp_port); + + return SWITCH_STATUS_SUCCESS; +} + + + +//? +SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_session_t *session, switch_core_media_params_t *params) + +{ + const char *err = NULL; + const char *val = NULL; + switch_rtp_flag_t flags[SWITCH_RTP_FLAG_INVALID] = {0}; + switch_status_t status = SWITCH_STATUS_SUCCESS; + char tmp[50]; + char *timer_name = NULL; + const char *var; + switch_rtp_engine_t *a_engine, *v_engine; + switch_media_handle_t *smh; + + 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]; + + + if (switch_channel_down(session->channel)) { + return SWITCH_STATUS_FALSE; + } + + + if (switch_rtp_ready(a_engine->rtp_session)) { + switch_rtp_reset_media_timer(a_engine->rtp_session); + } + + if ((var = switch_channel_get_variable(session->channel, "rtp_secure_media")) && switch_true(var)) { + switch_channel_set_flag(session->channel, CF_SECURE); + } + + if (switch_channel_test_flag(session->channel, CF_PROXY_MODE)) { + status = SWITCH_STATUS_SUCCESS; + goto end; + } + + if (!params->reinvite) { + if (switch_rtp_ready(a_engine->rtp_session)) { + if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE) && !switch_rtp_ready(v_engine->rtp_session)) { + goto video; + } + + status = SWITCH_STATUS_SUCCESS; + goto end; + } + } + + if ((status = switch_core_media_set_codec(session, 0, params->codec_flags)) != SWITCH_STATUS_SUCCESS) { + goto end; + } + + memset(flags, 0, sizeof(flags)); + flags[SWITCH_RTP_FLAG_DATAWAIT]++; + + if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && + !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { + flags[SWITCH_RTP_FLAG_AUTOADJ]++; + } + + if (switch_media_handle_test_media_flag(smh, SCMF_PASS_RFC2833) + || ((val = switch_channel_get_variable(session->channel, "pass_rfc2833")) && switch_true(val))) { + switch_channel_set_flag(session->channel, CF_PASS_RFC2833); + } + + + if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFLUSH) + || ((val = switch_channel_get_variable(session->channel, "rtp_autoflush")) && switch_true(val))) { + flags[SWITCH_RTP_FLAG_AUTOFLUSH]++; + } + + if (!(switch_media_handle_test_media_flag(smh, SCMF_REWRITE_TIMESTAMPS) || + ((val = switch_channel_get_variable(session->channel, "rtp_rewrite_timestamps")) && switch_true(val)))) { + flags[SWITCH_RTP_FLAG_RAW_WRITE]++; + } + + if (switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG)) { + smh->cng_pt = 0; + } else if (smh->cng_pt) { + flags[SWITCH_RTP_FLAG_AUTO_CNG]++; + } + +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (!strcasecmp(a_engine->read_impl.iananame, "L16")) { + flags[SWITCH_RTP_FLAG_BYTESWAP]++; + } +#endif + + if ((flags[SWITCH_RTP_FLAG_BYTESWAP]) && (val = switch_channel_get_variable(session->channel, "rtp_disable_byteswap")) && switch_true(val)) { + flags[SWITCH_RTP_FLAG_BYTESWAP] = 0; + } + + if (a_engine->rtp_session && params->reinvite) { + //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE); + //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE); + char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session); + switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session); + + 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)); + if (switch_rtp_ready(a_engine->rtp_session)) { + if (a_engine->codec_params.recv_pt != a_engine->codec_params.agreed_pt) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "%s Set audio receive payload in Re-INVITE for non-matching dynamic PT to %u\n", + switch_channel_get_name(session->channel), a_engine->codec_params.recv_pt); + + switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.recv_pt); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "%s Setting audio receive payload in Re-INVITE to %u\n", + switch_channel_get_name(session->channel), a_engine->codec_params.recv_pt); + switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.agreed_pt); + } + + } + goto video; + } else { + 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_channel_test_flag(session->channel, CF_PROXY_MEDIA)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n", + switch_channel_get_name(session->channel), + a_engine->codec_params.local_sdp_ip, + a_engine->codec_params.local_sdp_port, + a_engine->codec_params.remote_sdp_ip, + a_engine->codec_params.remote_sdp_port, a_engine->codec_params.agreed_pt, a_engine->read_impl.microseconds_per_packet / 1000); + + if (switch_rtp_ready(a_engine->rtp_session)) { + switch_rtp_set_default_payload(a_engine->rtp_session, a_engine->codec_params.agreed_pt); + + if (a_engine->codec_params.recv_pt != a_engine->codec_params.agreed_pt) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "%s Set audio receive payload to %u\n", switch_channel_get_name(session->channel), a_engine->codec_params.recv_pt); + + switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.recv_pt); + } else { + switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.agreed_pt); + } + + } + } + + switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.local_sdp_port); + switch_channel_set_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, a_engine->codec_params.local_sdp_ip); + switch_channel_set_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, tmp); + switch_channel_set_variable(session->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, a_engine->codec_params.adv_sdp_ip); + + if (a_engine->rtp_session && params->reinvite) { + const char *rport = NULL; + switch_port_t remote_rtcp_port = 0; + + + + if ((rport = switch_channel_get_variable(session->channel, "sip_remote_audio_rtcp_port"))) { + remote_rtcp_port = (switch_port_t)atoi(rport); + } + + if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port, + remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n", + a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port); + if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && + !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { + /* Reactivate the NAT buster flag. */ + switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); + } + } + goto video; + } + + if (switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) { + switch_core_media_proxy_remote_addr(session, NULL); + + memset(flags, 0, sizeof(flags)); + flags[SWITCH_RTP_FLAG_DATAWAIT]++; + flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++; + + if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && + !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { + flags[SWITCH_RTP_FLAG_AUTOADJ]++; + } + timer_name = NULL; + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n", + switch_channel_get_name(session->channel), + a_engine->codec_params.remote_sdp_ip, + a_engine->codec_params.remote_sdp_port, + a_engine->codec_params.remote_sdp_ip, + a_engine->codec_params.remote_sdp_port, a_engine->codec_params.agreed_pt, a_engine->read_impl.microseconds_per_packet / 1000); + + if (switch_rtp_ready(a_engine->rtp_session)) { + switch_rtp_set_default_payload(a_engine->rtp_session, a_engine->codec_params.agreed_pt); + } + + } else { + timer_name = smh->mparams->timer_name; + + if ((var = switch_channel_get_variable(session->channel, "rtp_timer_name"))) { + timer_name = (char *) var; + } + } + + if (switch_channel_up(session->channel)) { + a_engine->rtp_session = switch_rtp_new(a_engine->codec_params.remote_sdp_ip, + a_engine->codec_params.remote_sdp_port, + a_engine->codec_params.remote_sdp_ip, + a_engine->codec_params.remote_sdp_port, + a_engine->codec_params.agreed_pt, + a_engine->read_impl.samples_per_packet, + a_engine->codec_params.codec_ms * 1000, + flags, timer_name, &err, switch_core_session_get_pool(session)); + } + + if (switch_rtp_ready(a_engine->rtp_session)) { + uint8_t vad_in = (smh->mparams->vflags & VAD_IN); + uint8_t vad_out = (smh->mparams->vflags & VAD_OUT); + uint8_t inb = switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND; + uint32_t stun_ping = 0; + const char *ssrc; + + switch_core_media_set_rtp_session(session, SWITCH_MEDIA_TYPE_AUDIO, a_engine->rtp_session); + + + if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_ssrc"))) { + uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10); + switch_rtp_set_ssrc(a_engine->rtp_session, ssrc_ul); + } + + + switch_channel_set_flag(session->channel, CF_FS_RTP); + + switch_channel_set_variable_printf(session->channel, "sip_use_pt", "%d", a_engine->codec_params.agreed_pt); + + if ((val = switch_channel_get_variable(session->channel, "rtp_enable_vad_in")) && switch_true(val)) { + vad_in = 1; + } + if ((val = switch_channel_get_variable(session->channel, "rtp_enable_vad_out")) && switch_true(val)) { + vad_out = 1; + } + + if ((val = switch_channel_get_variable(session->channel, "rtp_disable_vad_in")) && switch_true(val)) { + vad_in = 0; + } + if ((val = switch_channel_get_variable(session->channel, "rtp_disable_vad_out")) && switch_true(val)) { + vad_out = 0; + } + + if ((smh->mparams->stun_flags & STUN_FLAG_SET) && (val = switch_channel_get_variable(session->channel, "rtp_stun_ping"))) { + int ival = atoi(val); + + if (ival <= 0) { + if (switch_true(val)) { + ival = 6; + } + } + + stun_ping = (ival * a_engine->read_impl.samples_per_second) / a_engine->read_impl.samples_per_packet; + } + + a_engine->ssrc = switch_rtp_get_ssrc(a_engine->rtp_session); + switch_channel_set_variable_printf(session->channel, "rtp_use_ssrc", "%u", a_engine->ssrc); + + + + if (smh->mparams->auto_rtp_bugs & RTP_BUG_IGNORE_MARK_BIT) { + a_engine->rtp_bugs |= RTP_BUG_IGNORE_MARK_BIT; + } + + if ((val = switch_channel_get_variable(session->channel, "rtp_manual_rtp_bugs"))) { + switch_core_media_parse_rtp_bugs(&a_engine->rtp_bugs, val); + } + + switch_rtp_intentional_bugs(a_engine->rtp_session, a_engine->rtp_bugs | smh->mparams->manual_rtp_bugs); + + if ((vad_in && inb) || (vad_out && !inb)) { + switch_rtp_enable_vad(a_engine->rtp_session, session, &a_engine->read_codec, SWITCH_VAD_FLAG_TALKING | SWITCH_VAD_FLAG_EVENTS_TALK | SWITCH_VAD_FLAG_EVENTS_NOTALK); + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n", + switch_channel_get_name(switch_core_session_get_channel(session)), vad_in ? "in" : "", vad_out ? "out" : ""); + } + + if (stun_ping) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting stun ping to %s:%d\n", smh->mparams->stun_ip, stun_ping); + + switch_rtp_activate_stun_ping(a_engine->rtp_session, smh->mparams->stun_ip, smh->mparams->stun_port, stun_ping, + (smh->mparams->stun_flags & STUN_FLAG_FUNNY) ? 1 : 0); + } + + if ((val = switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec")) || (val = smh->mparams->rtcp_audio_interval_msec)) { + const char *rport = switch_channel_get_variable(session->channel, "sip_remote_audio_rtcp_port"); + switch_port_t remote_port = 0; + if (rport) { + remote_port = (switch_port_t)atoi(rport); + } + if (!strcasecmp(val, "passthru")) { + switch_rtp_activate_rtcp(a_engine->rtp_session, -1, remote_port); + } else { + int interval = atoi(val); + if (interval < 100 || interval > 5000) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, + "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval); + } else { + switch_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_port); + } + } + } + + if ((val = switch_channel_get_variable(session->channel, "jitterbuffer_msec")) || (val = smh->mparams->jb_msec)) { + int jb_msec = atoi(val); + int maxlen = 0, max_drift = 0; + char *p, *q; + + if ((p = strchr(val, ':'))) { + p++; + maxlen = atoi(p); + if ((q = strchr(p, ':'))) { + q++; + max_drift = abs(atoi(q)); + } + } + + if (jb_msec < 20 || jb_msec > 10000) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, + "Invalid Jitterbuffer spec [%d] must be between 20 and 10000\n", jb_msec); + } else { + int qlen, maxqlen = 50; + + qlen = jb_msec / (a_engine->read_impl.microseconds_per_packet / 1000); + + if (qlen < 1) { + qlen = 3; + } + + if (maxlen) { + maxqlen = maxlen / (a_engine->read_impl.microseconds_per_packet / 1000); + } + + if (maxqlen < qlen) { + maxqlen = qlen * 5; + } + if (switch_rtp_activate_jitter_buffer(a_engine->rtp_session, qlen, maxqlen, + a_engine->read_impl.samples_per_packet, + a_engine->read_impl.samples_per_second, max_drift) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), + SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen); + switch_channel_set_flag(session->channel, CF_JITTERBUFFER); + if (!switch_false(switch_channel_get_variable(session->channel, "sip_jitter_buffer_plc"))) { + switch_channel_set_flag(session->channel, CF_JITTERBUFFER_PLC); + } + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), + SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen); + } + + } + } + + if ((val = switch_channel_get_variable(session->channel, "params->rtp_timeout_sec"))) { + int v = atoi(val); + if (v >= 0) { + params->rtp_timeout_sec = v; + } + } + + if ((val = switch_channel_get_variable(session->channel, "params->rtp_hold_timeout_sec"))) { + int v = atoi(val); + if (v >= 0) { + params->rtp_hold_timeout_sec = v; + } + } + + if (params->rtp_timeout_sec) { + a_engine->max_missed_packets = (a_engine->read_impl.samples_per_second * params->rtp_timeout_sec) / a_engine->read_impl.samples_per_packet; + + switch_rtp_set_max_missed_packets(a_engine->rtp_session, a_engine->max_missed_packets); + if (!params->rtp_hold_timeout_sec) { + params->rtp_hold_timeout_sec = params->rtp_timeout_sec * 10; + } + } + + if (params->rtp_hold_timeout_sec) { + a_engine->max_missed_hold_packets = (a_engine->read_impl.samples_per_second * params->rtp_hold_timeout_sec) / a_engine->read_impl.samples_per_packet; + } + + if (smh->te) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send payload to %u\n", smh->te); + switch_rtp_set_telephony_event(a_engine->rtp_session, smh->te); + switch_channel_set_variable_printf(session->channel, "sip_2833_send_payload", "%d", smh->te); + } + + if (smh->recv_te) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf receive payload to %u\n", smh->recv_te); + switch_rtp_set_telephony_recv_event(a_engine->rtp_session, smh->recv_te); + switch_channel_set_variable_printf(session->channel, "sip_2833_recv_payload", "%d", smh->recv_te); + } + + if (a_engine->codec_params.recv_pt != a_engine->codec_params.agreed_pt) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "%s Set audio receive payload to %u\n", switch_channel_get_name(session->channel), a_engine->codec_params.recv_pt); + + switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.recv_pt); + } + + 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))) { + smh->cng_pt = 0; + } + + if (((val = switch_channel_get_variable(session->channel, "rtp_digit_delay")))) { + int delayi = atoi(val); + if (delayi < 0) delayi = 0; + params->dtmf_delay = (uint32_t) delayi; + } + + + if (params->dtmf_delay) { + switch_rtp_set_interdigit_delay(a_engine->rtp_session, params->dtmf_delay); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "%s Set rtp dtmf delay to %u\n", switch_channel_get_name(session->channel), params->dtmf_delay); + + } + + if (smh->cng_pt && !switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", smh->cng_pt); + switch_rtp_set_cng_pt(a_engine->rtp_session, smh->cng_pt); + } + + switch_core_session_apply_crypto(session, SWITCH_MEDIA_TYPE_AUDIO, "rtp_secure_media_confirmed"); + + 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_channel_test_flag(session->channel, CF_ZRTP_PASSTHRU)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating ZRTP PROXY MODE\n"); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Disable NOTIMER_DURING_BRIDGE\n"); + switch_channel_clear_flag(session->channel, CF_NOTIMER_DURING_BRIDGE); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activating audio UDPTL mode\n"); + switch_rtp_udptl_mode(a_engine->rtp_session); + } + + + video: + + switch_core_media_check_video_codecs(session); + + if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE) && v_engine->codec_params.rm_encoding && v_engine->codec_params.remote_sdp_port) { + /******************************************************************************************/ + if (v_engine->rtp_session && params->reinvite) { + //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE); + //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE); + char *remote_host = switch_rtp_get_remote_host(v_engine->rtp_session); + switch_port_t remote_port = switch_rtp_get_remote_port(v_engine->rtp_session); + + + + if (remote_host && remote_port && !strcmp(remote_host, v_engine->codec_params.remote_sdp_ip) && remote_port == v_engine->codec_params.remote_sdp_port) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params are unchanged for %s.\n", + switch_channel_get_name(session->channel)); + goto video_up; + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params changed for %s from %s:%d to %s:%d\n", + switch_channel_get_name(session->channel), + remote_host, remote_port, v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port); + } + } + + if (!switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "VIDEO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n", switch_channel_get_name(session->channel), + a_engine->codec_params.remote_sdp_ip, v_engine->codec_params.local_sdp_port, v_engine->codec_params.remote_sdp_ip, + v_engine->codec_params.remote_sdp_port, v_engine->codec_params.agreed_pt, a_engine->read_impl.microseconds_per_packet / 1000); + + if (switch_rtp_ready(v_engine->rtp_session)) { + switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt); + } + } + + switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->codec_params.local_sdp_port); + switch_channel_set_variable(session->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, a_engine->codec_params.adv_sdp_ip); + switch_channel_set_variable(session->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, tmp); + + + if (v_engine->rtp_session && params->reinvite) { + const char *rport = NULL; + switch_port_t remote_rtcp_port = 0; + + params->reinvite = 0; + + if ((rport = switch_channel_get_variable(session->channel, "sip_remote_video_rtcp_port"))) { + remote_rtcp_port = (switch_port_t)atoi(rport); + } + + if (switch_rtp_set_remote_address + (v_engine->rtp_session, v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, + &err) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n", + v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port); + if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && + !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { + /* Reactivate the NAT buster flag. */ + switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ); + } + + } + goto video_up; + } + + if (switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) { + switch_core_media_proxy_remote_addr(session, NULL); + + memset(flags, 0, sizeof(flags)); + flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++; + flags[SWITCH_RTP_FLAG_DATAWAIT]++; + + if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && + !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { + flags[SWITCH_RTP_FLAG_AUTOADJ]++; + } + timer_name = NULL; + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "PROXY VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n", + switch_channel_get_name(session->channel), + a_engine->codec_params.remote_sdp_ip, + v_engine->codec_params.local_sdp_port, + v_engine->codec_params.remote_sdp_ip, + v_engine->codec_params.remote_sdp_port, v_engine->codec_params.agreed_pt, v_engine->read_impl.microseconds_per_packet / 1000); + + if (switch_rtp_ready(v_engine->rtp_session)) { + switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt); + } + } else { + timer_name = smh->mparams->timer_name; + + if ((var = switch_channel_get_variable(session->channel, "rtp_timer_name"))) { + timer_name = (char *) var; + } + } + + /******************************************************************************************/ + + if (v_engine->rtp_session) { + goto video_up; + } + + + if (!v_engine->codec_params.local_sdp_port) { + switch_core_media_choose_video_port(session, 1); + } + + memset(flags, 0, sizeof(flags)); + flags[SWITCH_RTP_FLAG_DATAWAIT]++; + flags[SWITCH_RTP_FLAG_RAW_WRITE]++; + + if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(session->channel, CF_PROXY_MODE) && + !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { + flags[SWITCH_RTP_FLAG_AUTOADJ]++; + } + + if (switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) { + flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++; + } + switch_core_media_set_video_codec(session, 0); + + flags[SWITCH_RTP_FLAG_USE_TIMER] = 0; + flags[SWITCH_RTP_FLAG_NOBLOCK] = 0; + flags[SWITCH_RTP_FLAG_VIDEO]++; + + v_engine->rtp_session = switch_rtp_new(a_engine->codec_params.remote_sdp_ip, + v_engine->codec_params.local_sdp_port, + v_engine->codec_params.remote_sdp_ip, + v_engine->codec_params.remote_sdp_port, + v_engine->codec_params.agreed_pt, + 1, 90000, flags, NULL, &err, switch_core_session_get_pool(session)); + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n", + switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "", + switch_channel_get_name(session->channel), + a_engine->codec_params.remote_sdp_ip, + v_engine->codec_params.local_sdp_port, + v_engine->codec_params.remote_sdp_ip, + v_engine->codec_params.remote_sdp_port, v_engine->codec_params.agreed_pt, + 0, switch_rtp_ready(v_engine->rtp_session) ? "SUCCESS" : err); + + + if (switch_rtp_ready(v_engine->rtp_session)) { + switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt); + switch_core_media_set_rtp_session(session, SWITCH_MEDIA_TYPE_VIDEO, v_engine->rtp_session); + } + + if (switch_rtp_ready(v_engine->rtp_session)) { + const char *ssrc; + switch_channel_set_flag(session->channel, CF_VIDEO); + if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_video_ssrc"))) { + uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10); + switch_rtp_set_ssrc(v_engine->rtp_session, ssrc_ul); + } + + + + if ((val = switch_channel_get_variable(session->channel, "rtp_manual_video_rtp_bugs"))) { + switch_core_media_parse_rtp_bugs(&v_engine->rtp_bugs, val); + } + + switch_rtp_intentional_bugs(v_engine->rtp_session, v_engine->rtp_bugs | smh->mparams->manual_video_rtp_bugs); + + if (v_engine->codec_params.recv_pt != v_engine->codec_params.agreed_pt) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "%s Set video receive payload to %u\n", switch_channel_get_name(session->channel), v_engine->codec_params.recv_pt); + switch_rtp_set_recv_pt(v_engine->rtp_session, v_engine->codec_params.recv_pt); + } + + switch_channel_set_variable_printf(session->channel, "sip_use_video_pt", "%d", v_engine->codec_params.agreed_pt); + v_engine->ssrc = switch_rtp_get_ssrc(v_engine->rtp_session); + switch_channel_set_variable_printf(session->channel, "rtp_use_video_ssrc", "%u", v_engine->ssrc); + + switch_core_session_apply_crypto(session, SWITCH_MEDIA_TYPE_VIDEO, "rtp_secure_video_confirmed"); + + + if ((val = switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec")) + || (val = smh->mparams->rtcp_audio_interval_msec)) { + const char *rport = switch_channel_get_variable(session->channel, "sip_remote_video_rtcp_port"); + switch_port_t remote_port = 0; + if (rport) { + remote_port = (switch_port_t)atoi(rport); + } + if (!strcasecmp(val, "passthru")) { + switch_rtp_activate_rtcp(a_engine->rtp_session, -1, remote_port); + } else { + int interval = atoi(val); + if (interval < 100 || interval > 5000) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, + "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval); + } else { + switch_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_port); + } + } + } + if (switch_channel_test_flag(session->channel, CF_ZRTP_PASSTHRU)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activating video UDPTL mode\n"); + switch_rtp_udptl_mode(v_engine->rtp_session); + } + + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err)); + switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + goto end; + } + } + + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err)); + switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + status = SWITCH_STATUS_FALSE; + goto end; + } + + video_up: + + status = SWITCH_STATUS_SUCCESS; + + end: + + params->reinvite = 0; + + switch_core_recovery_track(session); + + + + return status; + +} /* For Emacs: