diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 43bbf12d03..3694739f0b 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -351,7 +351,9 @@ typedef enum { ED_DTMF = (1 << 2), ED_COPY_DISPLAY = (1 << 3), ED_BRIDGE_READ = (1 << 4), - ED_BRIDGE_WRITE = (1 << 5) + ED_BRIDGE_WRITE = (1 << 5), + ED_TAP_READ = (1 << 6), + ED_TAP_WRITE = (1 << 7) } switch_eavesdrop_flag_enum_t; typedef uint32_t switch_eavesdrop_flag_t; diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 94fb59278a..6b8c8ad6c4 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -896,6 +896,35 @@ static int e_callback(void *pArg, int argc, char **argv, char **columnNames) return 1; } +#define native_eavesdrop_SYNTAX " [read|write]" +SWITCH_STANDARD_APP(native_eavesdrop_function) +{ + switch_eavesdrop_flag_t flags = ED_TAP_READ; + char *argv[2] = { 0 }; + int argc = 0; + char *mydata; + + + if (zstr(data)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "INVALID ARGS usage (%s)\n", native_eavesdrop_SYNTAX); + return; + } + + mydata = switch_core_session_strdup(session, data); + argc = switch_split(mydata, ' ', argv); + + if (argc > 1) { + if (switch_stristr("read", argv[1])) { + flags |= ED_TAP_READ; + } else if (switch_stristr("write", argv[1])) { + flags |= ED_TAP_WRITE; + } + } + + switch_ivr_eavesdrop_session(session, argv[0], NULL, flags); +} + + #define eavesdrop_SYNTAX "[all | ]" SWITCH_STANDARD_APP(eavesdrop_function) { @@ -6571,6 +6600,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "unblock_dtmf", "Stop blocking DTMF", "Stop blocking DTMF", dtmf_unblock_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "intercept", "intercept", "intercept", intercept_function, INTERCEPT_SYNTAX, SAF_NONE); SWITCH_ADD_APP(app_interface, "eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", eavesdrop_function, eavesdrop_SYNTAX, SAF_MEDIA_TAP); + SWITCH_ADD_APP(app_interface, "native_eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", native_eavesdrop_function, native_eavesdrop_SYNTAX, SAF_MEDIA_TAP); SWITCH_ADD_APP(app_interface, "three_way", "three way call with a uuid", "three way call with a uuid", three_way_function, threeway_SYNTAX, SAF_MEDIA_TAP); SWITCH_ADD_APP(app_interface, "set_user", "Set a User", "Set a User", set_user_function, SET_USER_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 7a8995f01a..e898cf393e 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -1848,12 +1848,13 @@ static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data switch_core_session_t *session = switch_core_media_bug_get_session(bug); switch_channel_t *e_channel = switch_core_session_get_channel(ep->eavesdropper); int show_spy = 0; - + switch_frame_t *nframe = NULL; + frame.data = data; frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; show_spy = switch_core_media_bug_test_flag(bug, SMBF_SPY_VIDEO_STREAM) || switch_core_media_bug_test_flag(bug, SMBF_SPY_VIDEO_STREAM_BLEG); - + if (show_spy) { if (!ep->set_decoded_read) { ep->set_decoded_read = 1; @@ -1891,6 +1892,12 @@ static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data switch_channel_clear_flag_recursive(switch_core_session_get_channel(session), CF_VIDEO_DECODED_READ); + break; + case SWITCH_ABC_TYPE_TAP_NATIVE_WRITE: + nframe = switch_core_media_bug_get_native_write_frame(bug); + break; + case SWITCH_ABC_TYPE_TAP_NATIVE_READ: + nframe = switch_core_media_bug_get_native_read_frame(bug); break; case SWITCH_ABC_TYPE_WRITE: break; @@ -1901,8 +1908,6 @@ static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data switch_buffer_zwrite(ep->buffer, frame.data, frame.datalen); switch_buffer_unlock(ep->buffer); } - } else { - return SWITCH_FALSE; } break; case SWITCH_ABC_TYPE_READ: @@ -1990,6 +1995,21 @@ static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data break; } + if (nframe) { + switch_frame_t frame = {0}; + uint8_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = ""; + + frame = *nframe; + frame.data = buf; + frame.codec = nframe->codec; + + memcpy(frame.data, nframe->data, nframe->datalen); + + if (switch_core_session_write_frame(ep->eavesdropper, nframe, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { + return SWITCH_FALSE; + } + } + return SWITCH_TRUE; } @@ -2127,9 +2147,19 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session goto end; } + if ((flags & ED_TAP_READ) || (flags & ED_TAP_WRITE)) { + switch_core_session_get_real_read_impl(tsession, &tread_impl); + switch_core_session_get_real_read_impl(session, &read_impl); + + if (strcasecmp(tread_impl.iananame, read_impl.iananame)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codecs do not match which is required for this mode\n"); + goto end; + } + } + switch_core_session_get_read_impl(tsession, &tread_impl); switch_core_session_get_read_impl(session, &read_impl); - + if ((id_name = switch_channel_get_variable(tchannel, "eavesdrop_announce_id"))) { const char *tmp = switch_channel_get_variable(tchannel, "eavesdrop_announce_macro"); if (tmp) { @@ -2217,18 +2247,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session ep->eavesdropper = session; ep->flags = flags; - switch_mutex_init(&ep->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession)); - switch_buffer_create_dynamic(&ep->buffer, buf_size, buf_size, buf_size); - switch_buffer_add_mutex(ep->buffer, ep->mutex); - - switch_mutex_init(&ep->w_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession)); - switch_buffer_create_dynamic(&ep->w_buffer, buf_size, buf_size, buf_size); - switch_buffer_add_mutex(ep->w_buffer, ep->w_mutex); - - switch_mutex_init(&ep->r_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession)); - switch_buffer_create_dynamic(&ep->r_buffer, buf_size, buf_size, buf_size); - switch_buffer_add_mutex(ep->r_buffer, ep->r_mutex); + if (!(flags & ED_TAP_READ) && !(flags & ED_TAP_WRITE)) { + switch_mutex_init(&ep->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession)); + switch_buffer_create_dynamic(&ep->buffer, buf_size, buf_size, buf_size); + switch_buffer_add_mutex(ep->buffer, ep->mutex); + + switch_mutex_init(&ep->w_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession)); + switch_buffer_create_dynamic(&ep->w_buffer, buf_size, buf_size, buf_size); + switch_buffer_add_mutex(ep->w_buffer, ep->w_mutex); + + switch_mutex_init(&ep->r_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession)); + switch_buffer_create_dynamic(&ep->r_buffer, buf_size, buf_size, buf_size); + switch_buffer_add_mutex(ep->r_buffer, ep->r_mutex); + } + if (flags & ED_BRIDGE_READ) { read_flags = SMBF_READ_STREAM | SMBF_READ_REPLACE; } @@ -2237,6 +2270,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session write_flags = SMBF_WRITE_STREAM | SMBF_WRITE_REPLACE; } + if (flags & ED_TAP_READ) { + read_flags = SMBF_TAP_NATIVE_READ; + write_flags = 0; + } + + if (flags & ED_TAP_WRITE) { + write_flags = SMBF_TAP_NATIVE_WRITE; + read_flags = 0; + } + + if (switch_channel_test_flag(session->channel, CF_VIDEO) && switch_channel_test_flag(tsession->channel, CF_VIDEO)) { if ((vval = switch_channel_get_variable(session->channel, "eavesdrop_show_listener_video"))) { if (switch_true(vval) || !strcasecmp(vval, "aleg") || !strcasecmp(vval, "bleg") || !strcasecmp(vval, "both")) { @@ -2284,6 +2328,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session name = cp->caller_id_name; num = cp->caller_id_number; + if ((flags & ED_TAP_READ) || (flags & ED_TAP_WRITE)) { + flags &= ~ED_DTMF; + flags &= ~ED_BRIDGE_READ; + flags &= ~ED_BRIDGE_WRITE; + } + if (flags & ED_COPY_DISPLAY) { if (switch_channel_test_flag(tchannel, CF_BRIDGE_ORIGINATOR) || !switch_channel_test_flag(tchannel, CF_BRIDGED)) { name = cp->callee_id_name; @@ -2425,7 +2475,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session } } - if (!switch_test_flag(read_frame, SFF_CNG)) { + if (ep->r_buffer && ep->w_buffer && !switch_test_flag(read_frame, SFF_CNG)) { switch_buffer_lock(ep->r_buffer); switch_buffer_zwrite(ep->r_buffer, read_frame->data, read_frame->datalen); switch_buffer_unlock(ep->r_buffer); @@ -2439,7 +2489,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session len = tlen; } - if (switch_buffer_inuse(ep->buffer) >= len) { + if (ep->buffer && switch_buffer_inuse(ep->buffer) >= len) { switch_buffer_lock(ep->buffer); while (switch_buffer_inuse(ep->buffer) >= len) { int tchanged = 0, changed = 0;