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
/* For Emacs:
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
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);
/*!
}
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);
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);
}
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");
sofia_set_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
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);
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);
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:
}
+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:
}
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)) {
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)
{
/*