From 0a0f5951ab616d5b136e79b7d4ad253510f9d0cc Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 1 Nov 2012 15:50:41 -0500 Subject: [PATCH] check in page app --- .../applications/mod_dptools/mod_dptools.c | 449 ++++++++++++++++++ 1 file changed, 449 insertions(+) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 5e6a732841..6f8084648a 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -4967,6 +4967,453 @@ SWITCH_STANDARD_APP(mutex_function) /* /// mutex /// */ +typedef struct page_data_s { + uint32_t *counter; + const char *dial_str; + const char *dp; + const char *context; + const char *exten; + const char *path; + switch_event_t *var_event; + switch_memory_pool_t *pool; + switch_mutex_t *mutex; +} page_data_t; + +static switch_status_t page_hanguphook(switch_core_session_t *session) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_channel_state_t state = switch_channel_get_state(channel); + + if (state == CS_HANGUP) { + page_data_t *pd; + + if ((pd = (page_data_t *) switch_channel_get_private(channel, "__PAGE_DATA"))) { + uint32_t *counter = pd->counter; + + switch_mutex_lock(pd->mutex); + (*counter)--; + switch_mutex_unlock(pd->mutex); + + + } + + switch_core_event_hook_remove_state_change(session, page_hanguphook); + } + + return SWITCH_STATUS_SUCCESS; +} + +void *SWITCH_THREAD_FUNC page_thread(switch_thread_t *thread, void *obj) +{ + page_data_t *mypd, *pd = (page_data_t *) obj; + switch_core_session_t *session; + switch_call_cause_t cause = SWITCH_CAUSE_NONE; + uint32_t *counter = pd->counter; + switch_memory_pool_t *pool = pd->pool; + + + if (switch_ivr_originate(NULL, &session, &cause, pd->dial_str, 60, NULL, NULL, NULL, NULL, pd->var_event, SOF_NONE, NULL) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(session); + + switch_channel_set_variable(channel, "page_file", pd->path); + + mypd = switch_core_session_alloc(session, sizeof(*mypd)); + mypd->counter = pd->counter; + mypd->mutex = pd->mutex; + switch_core_event_hook_add_state_change(session, page_hanguphook); + switch_channel_set_private(channel, "__PAGE_DATA", mypd); + switch_ivr_session_transfer(session, pd->exten, pd->dp, pd->context); + switch_core_session_rwunlock(session); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "originate failed: %s [%s]\n", switch_channel_cause2str(cause), pd->dial_str); + switch_mutex_lock(pd->mutex); + (*counter)--; + switch_mutex_unlock(pd->mutex); + } + + switch_event_safe_destroy(&pd->var_event); + + if (pool) { + switch_core_destroy_memory_pool(&pool); + } + + return NULL; +} + +static void launch_call(const char *dial_str, + const char *path, const char *exten, const char *context, const char *dp, + switch_mutex_t *mutex, uint32_t *counter, switch_event_t **var_event) +{ + switch_thread_data_t *td; + switch_memory_pool_t *pool; + page_data_t *pd; + + switch_core_new_memory_pool(&pool); + + pd = switch_core_alloc(pool, sizeof(*pd)); + pd->pool = pool; + pd->exten = switch_core_strdup(pool, exten); + pd->context = switch_core_strdup(pool, context); + pd->dp = switch_core_strdup(pool, dp); + pd->dial_str = switch_core_strdup(pool, dial_str); + pd->path = switch_core_strdup(pool, path); + pd->mutex = mutex; + + if (var_event && *var_event) { + switch_event_dup(&pd->var_event, *var_event); + switch_event_destroy(var_event); + } + + switch_mutex_lock(pd->mutex); + (*counter)++; + switch_mutex_unlock(pd->mutex); + + pd->counter = counter; + + td = switch_core_alloc(pool, sizeof(*td)); + td->func = page_thread; + td->obj = pd; + + switch_thread_pool_launch_thread(&td); + +} + +typedef struct call_monitor_s { + switch_memory_pool_t *pool; + const char *path; + char *data; + const char *context; + const char *exten; + const char *dp; + uint32_t chunk_size; + int nuke; +} call_monitor_t; + + + +void *SWITCH_THREAD_FUNC call_monitor_thread(switch_thread_t *thread, void *obj) +{ + call_monitor_t *cm = (call_monitor_t *) obj; + uint32_t sent = 0; + switch_mutex_t *mutex; + uint32_t counter = 0; + switch_memory_pool_t *pool = cm->pool; + int size; + char *argv[512] = { 0 }; + int busy = 0; + switch_event_t *var_event = NULL; + char *data; + + switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, cm->pool); + + if (switch_file_exists(cm->path, cm->pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File %s does not exist!\n", cm->path); + goto end; + } + + data = cm->data; + + while (data && *data && *data == ' ') { + data++; + } + + while (*data == '<') { + char *parsed = NULL; + + if (switch_event_create_brackets(data, '<', '>', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n"); + goto end; + } + + data = parsed; + } + + while (data && *data && *data == ' ') { + data++; + } + + if (!(size = switch_separate_string_string(data, SWITCH_ENT_ORIGINATE_DELIM, argv, (sizeof(argv) / sizeof(argv[0]))))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channels specified.\n"); + goto end; + } + + + if (cm->chunk_size > size) { + cm->chunk_size = size; + } + + while (sent < size) { + do { + switch_mutex_lock(mutex); + busy = (counter >= cm->chunk_size); + switch_mutex_unlock(mutex); + + if (busy) { + switch_yield(100000); + } + + } while (busy); + + printf("%ld ASS LAUNCH %s %d %d\n", (long)pthread_self(), argv[sent], sent, size); + + launch_call(argv[sent++], cm->path, cm->exten, cm->context, cm->dp, mutex, &counter, &var_event); + } + + + end: + + while(counter) { + switch_mutex_lock(mutex); + switch_mutex_unlock(mutex); + switch_yield(100000); + } + + if (cm->nuke && !zstr(cm->path)) { + unlink(cm->path); + } + + if (pool) { + switch_core_destroy_memory_pool(&pool); + } + + return NULL; +} + +static void launch_call_monitor(const char *path, int del, const char *data, uint32_t chunk_size, const char *exten, const char *context, const char *dp) +{ + switch_thread_data_t *td; + switch_memory_pool_t *pool; + call_monitor_t *cm; + + switch_core_new_memory_pool(&pool); + + cm = switch_core_alloc(pool, sizeof(*cm)); + + if (del) { + cm->nuke = 1; + } + + cm->pool = pool; + cm->path = switch_core_strdup(pool, path); + cm->data = switch_core_strdup(pool, data); + cm->exten = switch_core_strdup(pool, exten); + cm->context = switch_core_strdup(pool, context); + cm->dp = switch_core_strdup(pool, dp); + cm->chunk_size = chunk_size; + + td = switch_core_alloc(pool, sizeof(*td)); + td->func = call_monitor_thread; + td->obj = cm; + + switch_thread_pool_launch_thread(&td); + +} + + +#define PAGE_SYNTAX "[:_:]" +SWITCH_STANDARD_APP(page_function) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + uint32_t limit = 0; + const char *path = NULL; + switch_input_args_t args = { 0 }; + switch_file_handle_t fh = { 0 }; + uint32_t chunk_size = 10; + const char *l = NULL; + const char *tmp; + int del = 0, rate; + const char *exten; + const char *context = NULL; + const char *dp = "inline"; + const char *pdata = data; + + if (zstr(pdata)) { + pdata = switch_channel_get_variable(channel, "page_data"); + } + + if (zstr(pdata)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No channels specified.\n"); + return; + } + + + exten = switch_channel_get_variable(channel, "page_exten"); + context = switch_channel_get_variable(channel, "page_context"); + + if ((l = switch_channel_get_variable(channel, "page_dp"))) { + dp = l; + } + + + l = switch_channel_get_variable(channel, "page_record_limit"); + + if (l) { + if (*l == '+') { + l++; + } + if (l) { + limit = switch_atoui(l); + } + } + + if ((l = switch_channel_get_variable(channel, "page_record_thresh"))) { + fh.thresh = switch_atoui(l); + } + + if ((l = switch_channel_get_variable(channel, "page_chunk_size"))) { + uint32_t tmp = switch_atoui(l); + + if (tmp > 0) { + chunk_size = tmp; + } + } + + if ((l = switch_channel_get_variable(channel, "page_record_silence_hits"))) { + fh.silence_hits = switch_atoui(l); + } + + if ((tmp = switch_channel_get_variable(channel, "record_rate"))) { + rate = atoi(tmp); + if (rate > 0) { + fh.samplerate = rate; + } + } + + args.input_callback = on_dtmf; + + switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, ""); + + + if (!(path = switch_channel_get_variable(channel, "page_path"))) { + const char *beep; + + path = switch_core_session_sprintf(session, "%s%s%s.wav", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session)); + del = 1; + + if (!(beep = switch_channel_get_variable(channel, "page_beep"))) { + beep = "tone_stream://%(500,0, 620)"; + } + + switch_ivr_play_file(session, NULL, beep, NULL); + + + switch_ivr_record_file(session, &fh, path, &args, limit); + } + + if (zstr(exten)) { + exten = switch_core_session_sprintf(session, "playback:%s", path); + } + + if (switch_file_exists(path, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { + launch_call_monitor(path, del, pdata, chunk_size, exten, context, dp); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File %s does not exist\n", path); + } + +} + + +SWITCH_STANDARD_API(page_api_function) +{ + char *odata = NULL, *data = NULL; + switch_event_t *var_event = NULL; + const char *exten; + char *oexten = NULL; + const char *context = NULL; + const char *dp = "inline"; + const char *pdata = data; + const char *l; + uint32_t chunk_size = 10; + const char *path; + + + if (zstr(cmd)) { + stream->write_function(stream, "-ERR no data"); + goto end; + } + + odata = strdup(cmd); + data = odata; + + while (data && *data && *data == ' ') { + data++; + } + + while (*data == '(') { + char *parsed = NULL; + + if (switch_event_create_brackets(data, '(', ')', ',', &var_event, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n"); + goto end; + } + + data = parsed; + } + + while (data && *data && *data == ' ') { + data++; + } + + if (!var_event) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error!\n"); + goto end; + } + + pdata = data; + + if (zstr(pdata)) { + pdata = switch_event_get_header(var_event, "page_data"); + } + + if (zstr(pdata)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No channels specified.\n"); + goto end; + } + + + exten = switch_event_get_header(var_event, "page_exten"); + context = switch_event_get_header(var_event, "page_context"); + + if ((l = switch_event_get_header(var_event, "page_dp"))) { + dp = l; + } + + + if ((l = switch_event_get_header(var_event, "page_chunk_size"))) { + uint32_t tmp = switch_atoui(l); + + if (tmp > 0) { + chunk_size = tmp; + } + } + + if (!(path = switch_event_get_header(var_event, "page_path"))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No file specified.\n"); + goto end; + } + + if (zstr(exten)) { + oexten = switch_mprintf("playback:%s", path); + exten = oexten; + } + + if (switch_file_exists(path, NULL) == SWITCH_STATUS_SUCCESS) { + launch_call_monitor(path, 0, pdata, chunk_size, exten, context, dp); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File %s does not exist\n", path); + } + + + end: + + + switch_safe_free(odata); + switch_safe_free(oexten); + + return SWITCH_STATUS_SUCCESS; +} + + #define SPEAK_DESC "Speak text to a channel via the tts interface" #define DISPLACE_DESC "Displace audio from a file to the channels input" @@ -5044,6 +5491,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_CHAT(chat_interface, "api", api_chat_send); SWITCH_ADD_API(api_interface, "strepoch", "Convert a date string into epoch time", strepoch_api_function, ""); + SWITCH_ADD_API(api_interface, "page", "Send a file as a page", page_api_function, "(var1=val1,var2=val2)[:_:]"); SWITCH_ADD_API(api_interface, "strmicroepoch", "Convert a date string into micoepoch time", strmicroepoch_api_function, ""); SWITCH_ADD_API(api_interface, "chat", "chat", chat_api_function, "||||[]"); SWITCH_ADD_API(api_interface, "strftime", "strftime", strftime_api_function, ""); @@ -5073,6 +5521,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "hold", "Send a hold message", "Send a hold message", hold_function, HOLD_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "unhold", "Send a un-hold message", "Send a un-hold message", unhold_function, UNHOLD_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "mutex", "block on a call flow only allowing one at a time", "", mutex_function, MUTEX_SYNTAX, SAF_NONE); + SWITCH_ADD_APP(app_interface, "page", "", "", page_function, PAGE_SYNTAX, SAF_NONE); SWITCH_ADD_APP(app_interface, "transfer", "Transfer a channel", TRANSFER_LONG_DESC, transfer_function, " [ ]", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "check_acl", "Check an ip against an ACL list", "Check an ip against an ACL list", check_acl_function,