mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-13 12:40:17 +00:00
%FEATURE Add new feature to filter the SDP on bypass_media calls to remove or limit codecs.
VARIABLE: bypass_media_sdp_filter Can be set globally or per leg on the inbound side of a bypass_media bridge. VALID FILTERS: remove(): Removes the specified codec if it exists in the SDP. only(): Removes all codecs besides the one specified (providing that it exists in the sdp) (will not remove telephone-event)) EXAMPLE 1 (remove everything leaving only g729): <action application="set" data="bypass_media_sdp_filter=only(g729)"/> <action application="set" data="bypass_media=true"/> <action application="bridge" data="sofia/internal/1238@conference.freeswitch.org"/> EXAMPLE 2 (remove everything leaving only g729 and also remove dtmf): <action application="set" data="bypass_media_sdp_filter=only(g729)|remove(telephone-event)"/> <action application="set" data="bypass_media=true"/> <action application="bridge" data="sofia/internal/1238@conference.freeswitch.org"/> EXAMPLE 3 (remove alaw and speex): <action application="set" data="bypass_media_sdp_filter=remove(pcma)|remove(speex)"/> <action application="set" data="bypass_media=true"/> <action application="bridge" data="sofia/internal/1238@conference.freeswitch.org"/>
This commit is contained in:
parent
92a66fb1e7
commit
24084adf77
@ -678,6 +678,7 @@ SWITCH_DECLARE(void) switch_channel_release_device_record(switch_device_record_t
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_bind_device_state_handler(switch_device_state_function_t function, void *user_data);
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_unbind_device_state_handler(switch_device_state_function_t function);
|
||||
SWITCH_DECLARE(const char *) switch_channel_device_state2str(switch_device_state_t device_state);
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_pass_sdp(switch_channel_t *from_channel, switch_channel_t *to_channel, const char *sdp);
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
|
@ -275,7 +275,7 @@ SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_se
|
||||
SWITCH_DECLARE(switch_rtp_crypto_key_type_t) switch_core_media_crypto_str2type(const char *str);
|
||||
SWITCH_DECLARE(const char *) switch_core_media_crypto_type2str(switch_rtp_crypto_key_type_t type);
|
||||
SWITCH_DECLARE(int) switch_core_media_crypto_keylen(switch_rtp_crypto_key_type_t type);
|
||||
|
||||
SWITCH_DECLARE(char *) switch_core_media_filter_sdp(const char *sdp, const char *cmd, const char *arg);
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
|
@ -418,6 +418,7 @@ SWITCH_DECLARE(switch_status_t) switch_frame_alloc(switch_frame_t **frame, switc
|
||||
SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone);
|
||||
SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame);
|
||||
SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
|
||||
SWITCH_DECLARE(switch_bool_t) switch_is_leading_number(const char *str);
|
||||
SWITCH_DECLARE(char *) switch_find_parameter(const char *str, const char *param, switch_memory_pool_t *pool);
|
||||
|
||||
/*!
|
||||
|
@ -6567,9 +6567,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
}
|
||||
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
other_channel = switch_core_session_get_channel(other_session);
|
||||
if (!switch_channel_get_variable(other_channel, SWITCH_B_SDP_VARIABLE)) {
|
||||
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, r_sdp);
|
||||
}
|
||||
switch_channel_pass_sdp(channel, other_channel, r_sdp);
|
||||
|
||||
//switch_channel_pre_answer(other_channel);
|
||||
switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_PROGRESS);
|
||||
switch_core_session_rwunlock(other_session);
|
||||
@ -6626,9 +6625,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
other_channel = switch_core_session_get_channel(other_session);
|
||||
//other_tech_pvt = switch_core_session_get_private(other_session);
|
||||
|
||||
if (!switch_channel_get_variable(other_channel, SWITCH_B_SDP_VARIABLE)) {
|
||||
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, r_sdp);
|
||||
}
|
||||
switch_channel_pass_sdp(channel, other_channel, r_sdp);
|
||||
switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
|
||||
switch_core_session_rwunlock(other_session);
|
||||
}
|
||||
@ -7114,9 +7111,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
|
||||
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
other_channel = switch_core_session_get_channel(other_session);
|
||||
if (!switch_channel_get_variable(other_channel, SWITCH_B_SDP_VARIABLE)) {
|
||||
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, r_sdp);
|
||||
}
|
||||
switch_channel_pass_sdp(channel, other_channel, r_sdp);
|
||||
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_3PCC) && sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Got my ACK\n");
|
||||
@ -7218,9 +7213,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
|
||||
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
other_channel = switch_core_session_get_channel(other_session);
|
||||
if (!switch_channel_get_variable(other_channel, SWITCH_B_SDP_VARIABLE)) {
|
||||
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, r_sdp);
|
||||
}
|
||||
switch_channel_pass_sdp(channel, other_channel, r_sdp);
|
||||
|
||||
//switch_channel_answer(other_channel);
|
||||
switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
|
||||
|
@ -2401,7 +2401,8 @@ static void pass_sdp(verto_pvt_t *tech_pvt)
|
||||
|
||||
if (switch_core_session_get_partner(tech_pvt->session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
other_channel = switch_core_session_get_channel(other_session);
|
||||
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, tech_pvt->r_sdp);
|
||||
switch_channel_pass_sdp(tech_pvt->channel, other_channel, tech_pvt->r_sdp);
|
||||
|
||||
switch_channel_set_flag(other_channel, CF_PROXY_MODE);
|
||||
switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
|
||||
switch_core_session_rwunlock(other_session);
|
||||
|
@ -5220,6 +5220,65 @@ SWITCH_DECLARE(switch_status_t) switch_channel_unbind_device_state_handler(switc
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_pass_sdp(switch_channel_t *from_channel, switch_channel_t *to_channel, const char *sdp)
|
||||
{
|
||||
char *use_sdp = (char *) sdp;
|
||||
char *patched_sdp = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
if (!switch_channel_get_variable(to_channel, SWITCH_B_SDP_VARIABLE)) {
|
||||
const char *var;
|
||||
|
||||
if ((var = switch_channel_get_variable(from_channel, "bypass_media_sdp_filter"))) {
|
||||
char *cmd = switch_core_session_strdup(from_channel->session, var);
|
||||
int argc = 0;
|
||||
char *argv[50];
|
||||
int x = 0;
|
||||
|
||||
argc = switch_split(cmd, '|', argv);
|
||||
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *command = argv[x];
|
||||
char *arg = strchr(command, '(');
|
||||
|
||||
if (arg) {
|
||||
char *e = switch_find_end_paren(arg, '(', ')');
|
||||
*arg++ = '\0';
|
||||
if (e) *e = '\0';
|
||||
}
|
||||
|
||||
if (zstr(command) || zstr(arg)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(from_channel), SWITCH_LOG_WARNING, "%s SDP FILTER PARSE ERROR\n", from_channel->name);
|
||||
} else {
|
||||
char *tmp_sdp = NULL;
|
||||
|
||||
if (patched_sdp) {
|
||||
tmp_sdp = switch_core_media_filter_sdp(patched_sdp, command, arg);
|
||||
} else {
|
||||
tmp_sdp = switch_core_media_filter_sdp(use_sdp, command, arg);
|
||||
}
|
||||
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(from_channel), SWITCH_LOG_DEBUG,
|
||||
"Filter command %s(%s)\nFROM:\n==========\n%s\nTO:\n==========\n%s\n\n",
|
||||
command, arg, patched_sdp ? patched_sdp : use_sdp, tmp_sdp);
|
||||
|
||||
|
||||
if (tmp_sdp) {
|
||||
switch_safe_free(patched_sdp);
|
||||
patched_sdp = use_sdp = tmp_sdp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch_channel_set_variable(to_channel, SWITCH_B_SDP_VARIABLE, use_sdp);
|
||||
}
|
||||
|
||||
switch_safe_free(patched_sdp);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
|
@ -8854,6 +8854,220 @@ SWITCH_DECLARE(void) switch_core_media_deinit(void)
|
||||
|
||||
}
|
||||
|
||||
static int payload_number(const char *name)
|
||||
{
|
||||
if (!strcasecmp(name, "pcmu")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcasecmp(name, "pcma")) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
if (!strcasecmp(name, "gsm")) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (!strcasecmp(name, "g722")) {
|
||||
return 9;
|
||||
}
|
||||
|
||||
if (!strcasecmp(name, "g729")) {
|
||||
return 18;
|
||||
}
|
||||
|
||||
if (!strcasecmp(name, "dvi4")) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (!strcasecmp(name, "h261")) {
|
||||
return 31;
|
||||
}
|
||||
|
||||
if (!strcasecmp(name, "h263")) {
|
||||
return 34;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int find_pt(const char *sdp, const char *name)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if ((p = switch_stristr(name, sdp))) {
|
||||
if (p < end_of_p(sdp) && *(p+strlen(name)) == '/' && *(p-1) == ' ') {
|
||||
p -= 2;
|
||||
|
||||
while(*p > 47 && *p < 58) {
|
||||
p--;
|
||||
}
|
||||
p++;
|
||||
|
||||
if (p) {
|
||||
return atoi(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(char *) switch_core_media_filter_sdp(const char *sdp_str, const char *cmd, const char *arg)
|
||||
{
|
||||
char *new_sdp = NULL;
|
||||
int pt = -1, te = -1;
|
||||
switch_size_t len;
|
||||
const char *i;
|
||||
char *o;
|
||||
int in_m = 0, m_tally = 0, slash = 0;
|
||||
int number = 0, skip = 0;
|
||||
int remove = !strcasecmp(cmd, "remove");
|
||||
int only = !strcasecmp(cmd, "only");
|
||||
char *end = end_of_p((char *)sdp_str);
|
||||
int tst;
|
||||
end++;
|
||||
|
||||
|
||||
if (remove || only) {
|
||||
pt = payload_number(arg);
|
||||
|
||||
if (pt < 0) {
|
||||
pt = find_pt(sdp_str, arg);
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (only) {
|
||||
te = find_pt(sdp_str, "telephone-event");
|
||||
}
|
||||
|
||||
|
||||
len = strlen(sdp_str);
|
||||
new_sdp = malloc(len);
|
||||
o = new_sdp;
|
||||
i = sdp_str;
|
||||
|
||||
|
||||
while(i && *i && i < end) {
|
||||
|
||||
if (*i == 'm' && *(i+1) == '=') {
|
||||
in_m = 1;
|
||||
m_tally++;
|
||||
}
|
||||
|
||||
if (in_m) {
|
||||
if (*i == '\r' || *i == '\n') {
|
||||
in_m = 0;
|
||||
slash = 0;
|
||||
} else {
|
||||
if (*i == '/') {
|
||||
slash++;
|
||||
while(*i != ' ' && i < end) {
|
||||
*o++ = *i++;
|
||||
}
|
||||
|
||||
*o++ = *i++;
|
||||
}
|
||||
|
||||
if (slash && switch_is_leading_number(i)) {
|
||||
|
||||
|
||||
number = atoi(i);
|
||||
|
||||
while(i < end && ((*i > 47 && *i < 58) || *i == ' ')) {
|
||||
|
||||
if (remove) {
|
||||
tst = (number != pt);
|
||||
} else {
|
||||
tst = (number == pt || number == te);
|
||||
}
|
||||
|
||||
if (tst) {
|
||||
*o++ = *i;
|
||||
}
|
||||
i++;
|
||||
|
||||
if (*i == ' ') {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
tst = (number == pt);
|
||||
} else {
|
||||
tst = (number != pt && number != te);
|
||||
}
|
||||
|
||||
if (tst) {
|
||||
skip++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (i < end && !strncasecmp(i, "a=rtpmap:", 9)) {
|
||||
const char *t = i + 9;
|
||||
|
||||
number = atoi(t);
|
||||
|
||||
if (remove) {
|
||||
tst = (number == pt);
|
||||
} else {
|
||||
tst = (number != pt && number != te);
|
||||
}
|
||||
|
||||
while(i < end && (*i != '\r' && *i != '\n')) {
|
||||
if (!tst) *o++ = *i;
|
||||
i++;
|
||||
}
|
||||
|
||||
while(i < end && (*i == '\r' || *i == '\n')) {
|
||||
if (!tst) *o++ = *i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
while (i < end && !strncasecmp(i, "a=fmtp:", 7)) {
|
||||
const char *t = i + 7;
|
||||
|
||||
number = atoi(t);
|
||||
|
||||
if (remove) {
|
||||
tst = (number == pt);
|
||||
} else {
|
||||
tst = (number != pt && number != te);
|
||||
}
|
||||
|
||||
while(i < end && (*i != '\r' && *i != '\n')) {
|
||||
if (!tst) *o++ = *i;
|
||||
i++;
|
||||
}
|
||||
|
||||
while(i < end && (*i == '\r' || *i == '\n')) {
|
||||
if (!tst) *o++ = *i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
*o++ = *i;
|
||||
}
|
||||
|
||||
skip = 0;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
*o = '\0';
|
||||
|
||||
return new_sdp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
|
@ -654,7 +654,7 @@ SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_
|
||||
}
|
||||
|
||||
if ((val = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE))) {
|
||||
switch_channel_set_variable(peer_channel, SWITCH_B_SDP_VARIABLE, val);
|
||||
switch_channel_pass_sdp(channel, peer_channel, val);
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
|
||||
|
@ -1231,6 +1231,25 @@ SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str)
|
||||
return r;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_bool_t) switch_is_leading_number(const char *str)
|
||||
{
|
||||
const char *p;
|
||||
switch_bool_t r = SWITCH_FALSE;
|
||||
|
||||
if (*str == '-' || *str == '+') {
|
||||
str++;
|
||||
}
|
||||
|
||||
for (p = str; p && *p; p++) {
|
||||
if ((*p == '.' || (*p > 47 && *p < 58))) {
|
||||
r = SWITCH_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(const char *) switch_stristr(const char *instr, const char *str)
|
||||
{
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user