diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 169d356fdc..bf344e88db 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -474,7 +474,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(_In_ switch_channe #define switch_channel_stop_broadcast(_channel) if (switch_channel_test_flag(_channel, CF_BROADCAST)) switch_channel_set_flag(_channel, CF_BREAK | CF_STOP_BROADCAST) -#define switch_channel_media_ready(_channel) ((switch_channel_test_flag(_channel, CF_ANSWERED) || switch_channel_test_flag(_channel, CF_EARLY_MEDIA)) && !switch_channel_test_flag(_channel, CF_BYPASS_MEDIA)) +#define switch_channel_media_ready(_channel) ((switch_channel_test_flag(_channel, CF_ANSWERED) || switch_channel_test_flag(_channel, CF_EARLY_MEDIA)) && !switch_channel_test_flag(_channel, CF_PROXY_MODE)) /** @} */ diff --git a/src/include/switch_types.h b/src/include/switch_types.h index c487c2a4c5..8083814140 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -109,6 +109,7 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_CACHE_SPEECH_HANDLES_VARIABLE "cache_speech_handles" #define SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME "__cache_speech_handles_obj__" #define SWITCH_BYPASS_MEDIA_VARIABLE "bypass_media" +#define SWITCH_PROXY_MEDIA_VARIABLE "proxy_media" #define SWITCH_ENDPOINT_DISPOSITION_VARIABLE "endpoint_disposition" #define SWITCH_HOLD_MUSIC_VARIABLE "hold_music" #define SWITCH_EXPORT_VARS_VARIABLE "export_vars" @@ -389,7 +390,8 @@ typedef enum { SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 14), SWITCH_RTP_FLAG_AUTO_CNG = (1 << 15), SWITCH_RTP_FLAG_SECURE_SEND_RESET = (1 << 16), - SWITCH_RTP_FLAG_SECURE_RECV_RESET = (1 << 17) + SWITCH_RTP_FLAG_SECURE_RECV_RESET = (1 << 17), + SWITCH_RTP_FLAG_PROXY_MEDIA = (1 << 18) } switch_rtp_flag_t; @@ -666,7 +668,7 @@ CF_SERVICE = (1 << 9) - Channel has a service thread CF_TAGGED = (1 << 10) - Channel is tagged CF_WINNER = (1 << 11) - Channel is the winner CF_CONTROLLED = (1 << 12) - Channel is under control -CF_BYPASS_MEDIA = (1 << 13) - Channel has no media +CF_PROXY_MODE = (1 << 13) - Channel has no media CF_SUSPEND = (1 << 14) - Suspend i/o CF_EVENT_PARSE = (1 << 15) - Suspend control events CF_REPEAT_STATE = (1 << 16) - Tell the state machine to repeat a state @@ -697,7 +699,7 @@ typedef enum { CF_TAGGED = (1 << 10), CF_WINNER = (1 << 11), CF_CONTROLLED = (1 << 12), - CF_BYPASS_MEDIA = (1 << 13), + CF_PROXY_MODE = (1 << 13), CF_SUSPEND = (1 << 14), CF_EVENT_PARSE = (1 << 15), CF_REPEAT_STATE = (1 << 16), @@ -711,6 +713,7 @@ typedef enum { CF_RESET = (1 << 24), CF_ORIGINATING = (1 << 25), CF_STOP_BROADCAST = (1 << 26), + CF_PROXY_MEDIA = (1 << 27) } switch_channel_flag_t; @@ -732,7 +735,8 @@ typedef enum { SFF_RAW_RTP = (1 << 1), SFF_RTP_HEADER = (1 << 2), SFF_PLC = (1 << 3), - SFF_RFC2833 = (1 << 4) + SFF_RFC2833 = (1 << 4), + SFF_PROXY_PACKET = (1 << 5) } switch_frame_flag_t; diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index d48bb99056..4c68dfd6d9 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1228,14 +1228,18 @@ SWITCH_STANDARD_APP(audio_bridge_function) } continue_on_fail = switch_channel_get_variable(caller_channel, "continue_on_fail"); - - if (switch_channel_test_flag(caller_channel, CF_BYPASS_MEDIA) + + if ((var = switch_channel_get_variable(caller_channel, SWITCH_PROXY_MEDIA_VARIABLE)) && switch_true(var)) { + switch_channel_set_flag(caller_channel, CF_PROXY_MEDIA); + } + + if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || ((var = switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_VARIABLE)) && switch_true(var))) { if (!switch_channel_test_flag(caller_channel, CF_ANSWERED) && !switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA)) { - switch_channel_set_flag(caller_channel, CF_BYPASS_MEDIA); + switch_channel_set_flag(caller_channel, CF_PROXY_MODE); } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel is already up, delaying point-to-point mode 'till both legs are up.\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel is already up, delaying proxy mode 'till both legs are up.\n"); no_media_bridge = 1; } } @@ -1292,12 +1296,12 @@ SWITCH_STANDARD_APP(audio_bridge_function) } } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Redirecting media to point-to-point mode.\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Redirecting media to proxy mode.\n"); switch_ivr_nomedia(switch_core_session_get_uuid(session), SMF_FORCE); switch_ivr_nomedia(switch_core_session_get_uuid(peer_session), SMF_FORCE); switch_ivr_signal_bridge(session, peer_session); } else { - if (switch_channel_test_flag(caller_channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) { switch_ivr_signal_bridge(session, peer_session); } else { switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index afe6a44747..7d6dc384a2 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -80,7 +80,7 @@ static switch_status_t sofia_on_init(switch_core_session_t *session) tech_pvt->read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s SOFIA INIT\n", switch_channel_get_name(channel)); - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { sofia_glue_tech_absorb_sdp(tech_pvt); } @@ -340,11 +340,17 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) switch_set_flag_locked(tech_pvt, TFLAG_ANS); - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { const char *sdp = NULL; if ((sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE))) { tech_pvt->local_sdp_str = switch_core_session_strdup(session, sdp); } + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + sofia_glue_tech_patch_sdp(tech_pvt); + if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } + } } else { if (switch_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION)) { switch_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION); @@ -360,7 +366,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) } } - if ((status = sofia_glue_tech_choose_port(tech_pvt)) != SWITCH_STATUS_SUCCESS) { + if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return status; } @@ -612,7 +618,7 @@ static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_ switch_set_flag_locked(tech_pvt, TFLAG_WRITING); - if (!switch_test_flag(frame, SFF_CNG)) { + if (!switch_test_flag(frame, SFF_CNG) && !switch_test_flag(frame, SFF_PROXY_PACKET)) { if (tech_pvt->read_codec.implementation->encoded_bytes_per_frame) { bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame; frames = ((int) frame->datalen / bytes); @@ -758,7 +764,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi switch_channel_t *other_channel; const char *ip = NULL, *port = NULL; - switch_channel_set_flag(channel, CF_BYPASS_MEDIA); + switch_channel_set_flag(channel, CF_PROXY_MODE); tech_pvt->local_sdp_str = NULL; if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) { @@ -790,11 +796,11 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi { uint32_t count = 0; - switch_channel_clear_flag(channel, CF_BYPASS_MEDIA); + switch_channel_clear_flag(channel, CF_PROXY_MODE); tech_pvt->local_sdp_str = NULL; if (!switch_rtp_ready(tech_pvt->rtp_session)) { sofia_glue_tech_prepare_codecs(tech_pvt); - if ((status = sofia_glue_tech_choose_port(tech_pvt)) != SWITCH_STATUS_SUCCESS) { + if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return status; } @@ -957,10 +963,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi if (!switch_strlen_zero(((char *)msg->pointer_arg))) { nua_respond(tech_pvt->nh, code, reason, SIPTAG_CONTACT_STR(tech_pvt->reply_contact), - SOATAG_USER_SDP_STR(msg->pointer_arg), - SOATAG_AUDIO_AUX("cn telephone-event"), - NUTAG_INCLUDE_EXTRA_SDP(1), - TAG_END()); + SOATAG_USER_SDP_STR(msg->pointer_arg), + SOATAG_AUDIO_AUX("cn telephone-event"), + NUTAG_INCLUDE_EXTRA_SDP(1), + TAG_END()); } else { nua_respond(tech_pvt->nh, code, reason, SIPTAG_CONTACT_STR(tech_pvt->reply_contact), TAG_END()); } @@ -986,11 +992,17 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Asked to send early media by %s\n", msg->from); /* Transmit 183 Progress with SDP */ - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { const char *sdp = NULL; if ((sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE))) { tech_pvt->local_sdp_str = switch_core_session_strdup(session, sdp); } + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + sofia_glue_tech_patch_sdp(tech_pvt); + if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } + } } else { if (switch_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION)) { switch_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION); @@ -1008,7 +1020,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } } - if ((status = sofia_glue_tech_choose_port(tech_pvt)) != SWITCH_STATUS_SUCCESS) { + if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return status; } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 7fc55b9d65..13a0c9596f 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -165,7 +165,8 @@ typedef enum { TFLAG_SDP = (1 << 25), TFLAG_VIDEO = (1 << 26), TFLAG_TPORT_LOG = (1 << 27), - TFLAG_SENT_UPDATE = (1 << 28) + TFLAG_SENT_UPDATE = (1 << 28), + TFLAG_PROXY_MEDIA = (1 << 29) } TFLAGS; struct mod_sofia_globals { @@ -341,6 +342,7 @@ struct private_object { char *fmtp_out; char *remote_sdp_str; char *local_sdp_str; + char *orig_local_sdp_str; char *dest; char *dest_to; char *key; @@ -439,7 +441,7 @@ void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt); void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *profile, private_object_t *tech_pvt, const char *channame); -switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt); +switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt, int force); switch_status_t sofia_glue_do_invite(switch_core_session_t *session); @@ -584,3 +586,4 @@ char * sofia_glue_find_parameter(const char *str, const char *param); 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_glue_build_crypto(private_object_t *tech_pvt, int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction); +void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 110f98796a..6b4bff9855 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -971,6 +971,8 @@ switch_status_t config_sofia(int reload, char *profile_name) switch_set_flag(profile, TFLAG_INB_NOMEDIA); } else if (!strcasecmp(var, "inbound-late-negotiation") && switch_true(val)) { switch_set_flag(profile, TFLAG_LATE_NEGOTIATION); + } else if (!strcasecmp(var, "inbound-proxy-media") && switch_true(val)) { + switch_set_flag(profile, TFLAG_PROXY_MEDIA); } else if (!strcasecmp(var, "rfc2833-pt")) { profile->te = (switch_payload_t) atoi(val); } else if (!strcasecmp(var, "cng-pt")) { @@ -1316,7 +1318,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status const char *uuid; switch_core_session_t *other_session; - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { private_object_t *tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); @@ -1330,9 +1332,14 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status const char *r_sdp = NULL; switch_core_session_message_t msg = { 0 }; + if (sip->sip_payload && sip->sip_payload->pl_data && + sip->sip_content_type && sip->sip_content_type->c_subtype && switch_stristr("sdp", sip->sip_content_type->c_subtype)) { + r_sdp = sip->sip_payload->pl_data; + printf("WOOT\n%s\n", r_sdp); + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n", status, phrase); - tl_gets(tags, SOATAG_REMOTE_SDP_STR_REF(r_sdp), TAG_END()); msg.message_id = SWITCH_MESSAGE_INDICATE_RESPOND; msg.from = __FILE__; msg.numeric_arg = status; @@ -1493,7 +1500,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (status == 180) { switch_channel_mark_ring_ready(channel); if (!switch_channel_test_flag(channel, CF_GEN_RINGBACK)) { - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) { switch_core_session_message_t msg; @@ -1510,10 +1517,15 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } if (r_sdp) { - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { switch_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA); switch_channel_mark_pre_answered(channel); switch_set_flag(tech_pvt, TFLAG_SDP); + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { + goto done; + } + } if (!switch_channel_test_flag(channel, CF_GEN_RINGBACK) && (uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) { other_channel = switch_core_session_get_channel(other_session); @@ -1526,7 +1538,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } goto done; } else { - if (switch_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { + switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA"); + } else if (switch_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "DELAYED NEGOTIATION"); } else { if (sofia_glue_tech_media(tech_pvt, (char *) r_sdp) != SWITCH_STATUS_SUCCESS) { @@ -1546,7 +1560,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, case nua_callstate_received: if (tech_pvt && !switch_test_flag(tech_pvt, TFLAG_SDP)) { if (r_sdp && !switch_test_flag(tech_pvt, TFLAG_SDP)) { - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOMEDIA"); switch_set_flag_locked(tech_pvt, TFLAG_READY); if (switch_channel_get_state(channel) == CS_NEW) { @@ -1554,6 +1568,12 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } switch_set_flag(tech_pvt, TFLAG_SDP); goto done; + } else if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { + switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA"); + switch_set_flag_locked(tech_pvt, TFLAG_READY); + if (switch_channel_get_state(channel) == CS_NEW) { + switch_channel_set_state(channel, CS_INIT); + } } else if (switch_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION)) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "DELAYED NEGOTIATION"); switch_set_flag_locked(tech_pvt, TFLAG_READY); @@ -1627,16 +1647,19 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); } } else { - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { goto done; } else { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP"); - sofia_glue_tech_choose_port(tech_pvt); + sofia_glue_tech_choose_port(tech_pvt, 0); sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0); switch_channel_set_state(channel, CS_HIBERNATE); nua_respond(tech_pvt->nh, SIP_200_OK, SIPTAG_CONTACT_STR(tech_pvt->profile->url), - SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END()); + SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), + SOATAG_AUDIO_AUX("cn telephone-event"), + NUTAG_INCLUDE_EXTRA_SDP(1), + TAG_END()); goto done; } } @@ -1656,7 +1679,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, uint8_t match = 0; if (r_sdp) { - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) { switch_core_session_message_t msg = { 0 }; @@ -1681,7 +1704,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } } if (match) { - if (sofia_glue_tech_choose_port(tech_pvt) != SWITCH_STATUS_SUCCESS) { + if (sofia_glue_tech_choose_port(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { goto done; } sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0); @@ -1713,7 +1736,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, switch_set_flag_locked(tech_pvt, TFLAG_REINVITE); tech_pvt->nh = tech_pvt->nh2; tech_pvt->nh2 = NULL; - if (sofia_glue_tech_choose_port(tech_pvt) == SWITCH_STATUS_SUCCESS) { + if (sofia_glue_tech_choose_port(tech_pvt, 0) == SWITCH_STATUS_SUCCESS) { if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cheater Reinvite RTP Error!\n"); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); @@ -1740,10 +1763,15 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, r_sdp = (const char *) switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); } if (r_sdp && !switch_test_flag(tech_pvt, TFLAG_SDP)) { - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { switch_set_flag_locked(tech_pvt, TFLAG_ANS); switch_set_flag_locked(tech_pvt, TFLAG_SDP); switch_channel_mark_answered(channel); + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { + goto done; + } + } if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) { other_channel = switch_core_session_get_channel(other_session); @@ -1770,7 +1798,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (match) { switch_set_flag_locked(tech_pvt, TFLAG_ANS); - if (sofia_glue_tech_choose_port(tech_pvt) == SWITCH_STATUS_SUCCESS) { + if (sofia_glue_tech_choose_port(tech_pvt, 0) == SWITCH_STATUS_SUCCESS) { if (sofia_glue_activate_rtp(tech_pvt, 0) == SWITCH_STATUS_SUCCESS) { switch_channel_mark_answered(channel); } else { @@ -1863,7 +1891,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t goto done; } - if (switch_channel_test_flag(channel_a, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel_a, CF_PROXY_MODE)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Transfer on bypass media not allowed.\n"); nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"), SIPTAG_EVENT_STR(etmp), TAG_END()); @@ -2558,7 +2586,11 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "INBOUND CALL"); if (switch_test_flag(tech_pvt, TFLAG_INB_NOMEDIA)) { - switch_channel_set_flag(channel, CF_BYPASS_MEDIA); + switch_channel_set_flag(channel, CF_PROXY_MODE); + } + + if (switch_test_flag(tech_pvt, TFLAG_PROXY_MEDIA)) { + switch_channel_set_flag(channel, CF_PROXY_MEDIA); } if (!tech_pvt->call_id && sip->sip_call_id && sip->sip_call_id->i_id) { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index c0a716310a..eb3c69d926 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -54,7 +54,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32 use_cng = 0; } - if (!force && !ip && !sr && switch_channel_test_flag(tech_pvt->channel, CF_BYPASS_MEDIA)) { + if (!force && !ip && !sr && (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA))) { return; } @@ -321,7 +321,7 @@ void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt) const char *abs, *codec_string = NULL; const char *ocodec = NULL; - if (switch_channel_test_flag(tech_pvt->channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { goto end; } @@ -475,15 +475,22 @@ const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name) return NULL; } -switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt) +switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt, int force) { char *ip = tech_pvt->profile->rtpip; switch_port_t sdp_port; char tmp[50]; - if (switch_channel_test_flag(tech_pvt->channel, CF_BYPASS_MEDIA) || tech_pvt->adv_sdp_audio_port) { - return SWITCH_STATUS_SUCCESS; + if (!force) { + if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || + switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) || tech_pvt->adv_sdp_audio_port) { + return SWITCH_STATUS_SUCCESS; + } } + if (tech_pvt->adv_sdp_audio_port) { + switch_rtp_release_port(tech_pvt->adv_sdp_audio_ip, tech_pvt->adv_sdp_audio_port); + } + tech_pvt->local_sdp_audio_ip = ip; if (!(tech_pvt->local_sdp_audio_port = switch_rtp_request_port(tech_pvt->profile->rtpip))) { @@ -515,7 +522,7 @@ switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt) switch_port_t sdp_port; char tmp[50]; - if (switch_channel_test_flag(tech_pvt->channel, CF_BYPASS_MEDIA) || tech_pvt->adv_sdp_video_port) { + 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; } @@ -678,6 +685,119 @@ char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char return new_uri; } +static switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt) { + char rip[128] = ""; + char rp[128] = ""; + char *p, *ip_ptr = NULL, *port_ptr = NULL; + int x; + + if (switch_strlen_zero(tech_pvt->remote_sdp_str)) { + return SWITCH_STATUS_FALSE; + } + + if ((p = (char *)switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str))) { + ip_ptr = p + 9; + } + + if ((p = (char *)switch_stristr("m=audio ", tech_pvt->remote_sdp_str))) { + port_ptr = p + 8; + } + + if (!(ip_ptr && port_ptr)) { + return SWITCH_STATUS_FALSE; + } + + p = ip_ptr; + x = 0; + while(x < sizeof(rip) && p && *p && ((*p >= '0' && *p <= '9') || *p == '.')) { + rip[x++] = *p; + p++; + } + + p = port_ptr; + x = 0; + while(x < sizeof(rp) && p && *p && (*p >= '0' && *p <= '9')) { + rp[x++] = *p; + p++; + } + + 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); + + return SWITCH_STATUS_SUCCESS; +} + + +void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt) +{ + switch_size_t len; + char *p, *q, *ip_ptr = NULL, *port_ptr = NULL; + int x; + + if (switch_strlen_zero(tech_pvt->local_sdp_str)) { + return; + } + + if (!switch_strlen_zero(tech_pvt->orig_local_sdp_str)) { + return; + } + + len = strlen(tech_pvt->local_sdp_str) + 256; + + if ((p = (char *)switch_stristr("c=IN IP4 ", tech_pvt->local_sdp_str))) { + ip_ptr = p + 9; + } + + if ((p = (char *)switch_stristr("m=audio ", tech_pvt->local_sdp_str))) { + port_ptr = p + 8; + } + + if (!(ip_ptr && port_ptr)) { + return; + } + + if (sofia_glue_tech_choose_port(tech_pvt, 1) != SWITCH_STATUS_SUCCESS) { + return; + } + + tech_pvt->orig_local_sdp_str = tech_pvt->local_sdp_str; + tech_pvt->local_sdp_str = switch_core_session_alloc(tech_pvt->session, len); + + q = tech_pvt->local_sdp_str; + p = tech_pvt->orig_local_sdp_str; + + while (p && *p) { + if (p == ip_ptr) { + strncpy(q, tech_pvt->adv_sdp_audio_ip, strlen(tech_pvt->adv_sdp_audio_ip)); + q += strlen(tech_pvt->adv_sdp_audio_ip); + x = 0; + while(p && *p && ((*p >= '0' && *p <= '9') || *p == '.')) { + p++; + } + + } else if (p == port_ptr) { + char port_buf[25] = ""; + + switch_snprintf(port_buf, sizeof(port_buf), "%u", tech_pvt->adv_sdp_audio_port); + strncpy(q, port_buf, strlen(port_buf)); + q += strlen(port_buf); + x = 0; + while(p && *p && (*p >= '0' && *p <= '9')) { + p++; + } + } + + *q++ = *p++; + } + + tech_pvt->iananame = switch_core_session_strdup(tech_pvt->session, "NO-NAME"); + + tech_pvt->rm_rate = 8000; + tech_pvt->codec_ms = 20; + +} + + switch_status_t sofia_glue_do_invite(switch_core_session_t *session) { char *alert_info = NULL; @@ -725,7 +845,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) max_forwards = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE); - if ((status = sofia_glue_tech_choose_port(tech_pvt)) != SWITCH_STATUS_SUCCESS) { + if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) { return status; } @@ -793,17 +913,17 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) } } - if (!sofia_test_pflag(tech_pvt->profile, PFLAG_TLS) && sofia_glue_transport_has_tls(tech_pvt->transport)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "TLS not supported by profile\n"); + if (!sofia_test_pflag(tech_pvt->profile, PFLAG_TLS) && sofia_glue_transport_has_tls(tech_pvt->transport)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "TLS not supported by profile\n"); return SWITCH_STATUS_FALSE; - } + } - if (switch_strlen_zero(tech_pvt->invite_contact)) - { - if (sofia_glue_transport_has_tls(tech_pvt->transport)) + if (switch_strlen_zero(tech_pvt->invite_contact)) { + if (sofia_glue_transport_has_tls(tech_pvt->transport)) { tech_pvt->invite_contact = tech_pvt->profile->tls_url; - else + } else { tech_pvt->invite_contact = tech_pvt->profile->url; + } } url_str = sofia_overcome_sip_uri_weakness(session, url, tech_pvt->transport, SWITCH_TRUE); @@ -835,6 +955,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) } else if (switch_test_flag(caller_profile, SWITCH_CPF_HIDE_NUMBER)) { priv = "full"; } + if (switch_test_flag(caller_profile, SWITCH_CPF_SCREEN)) { screen = "yes"; } @@ -908,6 +1029,10 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) } } + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + sofia_glue_tech_patch_sdp(tech_pvt); + } + nua_invite(tech_pvt->nh, NUTAG_AUTOANSWER(0), NUTAG_SESSION_TIMER(session_timeout), @@ -1265,11 +1390,11 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f 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; + switch_assert(tech_pvt != NULL); - - if (switch_channel_test_flag(tech_pvt->channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) { return SWITCH_STATUS_SUCCESS; } @@ -1346,6 +1471,16 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f goto video; } + if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { + if ((status = sofia_glue_tech_proxy_remote_addr(tech_pvt)) != SWITCH_STATUS_SUCCESS) { + return status; + } + flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT); + timer_name = NULL; + } else { + timer_name = tech_pvt->profile->timer_name; + } + 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, @@ -1354,7 +1489,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f tech_pvt->read_codec.implementation->samples_per_frame, tech_pvt->codec_ms * 1000, (switch_rtp_flag_t) flags, - tech_pvt->profile->timer_name, + timer_name, &err, switch_core_session_get_pool(tech_pvt->session)); @@ -1519,7 +1654,7 @@ switch_status_t sofia_glue_tech_media(private_object_t *tech_pvt, const char *r_ } if (match) { - if (sofia_glue_tech_choose_port(tech_pvt) != SWITCH_STATUS_SUCCESS) { + if (sofia_glue_tech_choose_port(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { @@ -2006,7 +2141,7 @@ void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp) if (!switch_test_flag(tech_pvt, TFLAG_CHANGE_MEDIA) && (switch_channel_test_flag(other_channel, CF_OUTBOUND) && switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND) && - switch_channel_test_flag(tech_pvt->channel, CF_BYPASS_MEDIA))) { + switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) { switch_ivr_nomedia(val, SMF_FORCE); switch_set_flag_locked(tech_pvt, TFLAG_CHANGE_MEDIA); } diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 941b16b6b4..b019fa3dd7 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -130,6 +130,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_assert(session != NULL); switch_assert(*frame != NULL); + if (switch_test_flag(*frame, SFF_PROXY_PACKET)) { + /* Fast PASS! */ + status = SWITCH_STATUS_SUCCESS; + goto done; + } + if (switch_test_flag(*frame, SFF_CNG)) { status = SWITCH_STATUS_SUCCESS; if (!session->bugs) { @@ -465,6 +471,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess return SWITCH_STATUS_SUCCESS; } + if (switch_test_flag(frame, SFF_PROXY_PACKET)) { + /* Fast PASS! */ + return perform_write(session, frame, timeout, flag, stream_id); + } + if (switch_test_flag(frame, SFF_CNG)) { if (switch_channel_test_flag(session->channel, CF_ACCEPT_CNG)) { return perform_write(session, frame, timeout, flag, stream_id); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 87426ea3b6..7f80c0dea3 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -306,8 +306,12 @@ SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_ switch_channel_set_variable(peer_channel, SWITCH_B_SDP_VARIABLE, val); } - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { - switch_channel_set_flag(peer_channel, CF_BYPASS_MEDIA); + if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { + switch_channel_set_flag(peer_channel, CF_PROXY_MODE); + } + + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + switch_channel_set_flag(peer_channel, CF_PROXY_MEDIA); } if (profile) { @@ -1031,7 +1035,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_exten(switch_core_se goto done; } - if (switch_channel_test_flag(session->channel, CF_BYPASS_MEDIA) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) { + if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application %s Cannot be used with NO_MEDIA mode!\n", extension->current_application->application_name); status = SWITCH_STATUS_FALSE; diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index f82fb5e5f7..0a359e2afd 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -153,7 +153,7 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) return; } - if (switch_channel_test_flag(session->channel, CF_BYPASS_MEDIA) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) { + if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) { switch_ivr_media(session->uuid_str, SMF_NONE); nomedia++; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Application %s Requires media on channel %s!\n", diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 3f4488da55..4e0765cf27 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -753,7 +753,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_ swap = 1; } - if (switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { status = SWITCH_STATUS_SUCCESS; switch_core_session_receive_message(session, &msg); @@ -805,7 +805,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_nomedia(const char *uuid, switch_medi swap = 1; } - if ((flags & SMF_FORCE) || !switch_channel_test_flag(channel, CF_BYPASS_MEDIA)) { + if ((flags & SMF_FORCE) || !switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_core_session_receive_message(session, &msg); if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) && diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 86a28459a1..a7521491f7 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -1696,7 +1696,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(const char *uuid, const cha mypath = strdup(path); - if ((nomedia = switch_channel_test_flag(channel, CF_BYPASS_MEDIA))) { + if ((nomedia = switch_channel_test_flag(channel, CF_PROXY_MODE))) { switch_ivr_media(uuid, SMF_REBRIDGE); } diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 84ec6a53f7..9c735edb09 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -278,7 +278,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t } - if (read_codec && (ringback_data || !switch_channel_test_flag(caller_channel, CF_BYPASS_MEDIA))) { + if (read_codec && (ringback_data || + (!(switch_channel_test_flag(caller_channel, CF_PROXY_MODE) && switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA))))) { if (!(pass = (uint8_t) switch_test_flag(read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH))) { if (switch_core_codec_init(&write_codec, "L16", @@ -915,7 +916,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } if (session && (read_codec = switch_core_session_get_read_codec(session)) && - (ringback_data || !switch_channel_test_flag(caller_channel, CF_BYPASS_MEDIA))) { + (ringback_data || + (!(switch_channel_test_flag(caller_channel, CF_PROXY_MODE) && switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA))))) { if (!(pass = (uint8_t) switch_test_flag(read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH))) { if (switch_core_codec_init(&write_codec, @@ -1027,7 +1029,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } /* read from the channel while we wait if the audio is up on it */ - if (session && (ringback_data || !switch_channel_test_flag(caller_channel, CF_BYPASS_MEDIA)) && + if (session && (ringback_data || + !(switch_channel_test_flag(caller_channel, CF_PROXY_MODE) && switch_channel_test_flag(caller_channel, CF_PROXY_MODE))) && (switch_channel_test_flag(caller_channel, CF_ANSWERED) || switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA))) { switch_status_t tstatus = switch_core_session_read_frame(session, &read_frame, 1000, 0); @@ -1085,7 +1088,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess idx = IDX_CANCEL; } - if (session && (ringback_data || !switch_channel_test_flag(caller_channel, CF_BYPASS_MEDIA))) { + if (session && (ringback_data || !(switch_channel_test_flag(caller_channel, CF_PROXY_MODE) && + switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)))) { switch_core_session_reset(session, SWITCH_FALSE); } diff --git a/src/switch_pcm.c b/src/switch_pcm.c index 9527a61187..09c9a9640a 100644 --- a/src/switch_pcm.c +++ b/src/switch_pcm.c @@ -93,6 +93,39 @@ static switch_status_t switch_raw_destroy(switch_codec_t *codec) } + +static switch_status_t switch_nn_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) +{ + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t switch_nn_encode(switch_codec_t *codec, + switch_codec_t *other_codec, + void *decoded_data, + uint32_t decoded_data_len, + uint32_t decoded_rate, void *encoded_data, uint32_t * encoded_data_len, uint32_t * encoded_rate, + unsigned int *flag) +{ + /* NOOP indicates that the audio in is already the same as the audio out, so no conversion was necessary. */ + return SWITCH_STATUS_NOOP; +} + +static switch_status_t switch_nn_decode(switch_codec_t *codec, + switch_codec_t *other_codec, + void *encoded_data, + uint32_t encoded_data_len, + uint32_t encoded_rate, void *decoded_data, uint32_t * decoded_data_len, uint32_t * decoded_rate, + unsigned int *flag) +{ + return SWITCH_STATUS_NOOP; +} + +static switch_status_t switch_nn_destroy(switch_codec_t *codec) +{ + return SWITCH_STATUS_SUCCESS; +} + + static switch_status_t switch_g711u_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) { int encoding, decoding; @@ -261,12 +294,20 @@ static void mod_g711_load(switch_loadable_module_interface_t **module_interface, SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load) { switch_codec_interface_t *codec_interface; - int mpf = 10000, spf = 80, bpf = 160, ebpf = 160, bps = 128000, rate = 8000, counta, countb; + int mpf = 10000, spf = 80, bpf = 160, ebpf = 160, bps = 128000, rate = 8000, counta = 1, countb = 12; switch_payload_t ianacode[4] = { 0, 10, 117, 119 }; /* connect my internal structure to the blank pointer passed to me */ - *module_interface = switch_loadable_module_create_module_interface(pool, "PCM"); + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + SWITCH_ADD_CODEC(codec_interface, "NO-NAME PASS-THROUGH"); + switch_core_codec_add_implementation(pool, codec_interface, + SWITCH_CODEC_TYPE_AUDIO, 0, "NO-NAME", NULL, 8000, 8000, 0, + 20000, 160, 320, 320, 1, 1, 12, + switch_nn_init, switch_nn_encode, switch_nn_decode, switch_nn_destroy); + SWITCH_ADD_CODEC(codec_interface, "RAW Signed Linear (16 bit)"); + for (counta = 1; counta <= 3; counta++) { for (countb = 12; countb > 0; countb--) { switch_core_codec_add_implementation(pool, codec_interface, @@ -292,6 +333,8 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load) 40000, 441, 882, 882, 1, 1, 1, switch_raw_init, switch_raw_encode, switch_raw_decode, switch_raw_destroy); + + /* indicate that the module should continue to be loaded */ mod_g711_load(module_interface, pool); diff --git a/src/switch_rtp.c b/src/switch_rtp.c index fad958edb0..9d131774d9 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -688,8 +688,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session if (!switch_strlen_zero(timer_name)) { if (switch_core_timer_init(&rtp_session->timer, timer_name, ms_per_packet / 1000, samples_per_interval, pool) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting timer [%s] %d bytes per %dms\n", timer_name, samples_per_interval, - ms_per_packet); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + "Starting timer [%s] %d bytes per %dms\n", timer_name, samples_per_interval, ms_per_packet); } else { memset(&rtp_session->timer, 0, sizeof(rtp_session->timer)); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error starting timer [%s], async RTP disabled\n", timer_name); @@ -1038,6 +1038,13 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ bytes = sizeof(rtp_msg_t); status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock, 0, (void *) &rtp_session->recv_msg, &bytes); + + if (bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA)) { + /* Fast PASS! */ + *flags |= SFF_PROXY_PACKET; + ret = (int) bytes; + goto end; + } if (!SWITCH_STATUS_IS_BREAK(status) && rtp_session->timer.interval) { switch_core_timer_step(&rtp_session->timer); @@ -1785,11 +1792,26 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra uint32_t len, ts = 0; switch_payload_t payload; rtp_msg_t *send_msg = NULL; - + if (!switch_rtp_ready(rtp_session) || !rtp_session->remote_addr) { return -1; } + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA)) { + switch_size_t bytes; + + /* Fast PASS! */ + if (!switch_test_flag(frame, SFF_PROXY_PACKET)) { + return 0; + } + bytes = frame->packetlen; + if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) { + return -1; + } + return (int) bytes; + } + + fwd = (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_RAW_WRITE) && switch_test_flag(frame, SFF_RAW_RTP)) ? 1 : 0; switch_assert(frame != NULL);