static switch_status_t handle_msg_sendevent(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char ename[MAXATOMLEN + 1]; char esname[MAXATOMLEN + 1]; int headerlength; memset(esname, 0, MAXATOMLEN); if (ei_decode_atom(buf->buff, &buf->index, ename) || (!strncasecmp(ename, "CUSTOM", MAXATOMLEN) && ei_decode_atom(buf->buff, &buf->index, esname)) || ei_decode_list_header(buf->buff, &buf->index, &headerlength)) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { switch_event_types_t etype; if (switch_name_event(ename, &etype) == SWITCH_STATUS_SUCCESS) { switch_event_t *event; if ((strlen(esname) && switch_event_create_subclass(&event, etype, esname) == SWITCH_STATUS_SUCCESS) || switch_event_create(&event, etype) == SWITCH_STATUS_SUCCESS) { char key[1024]; char *value; int type; int size; int i = 0; switch_bool_t fail = SWITCH_FALSE; while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; ei_get_type(buf->buff, &buf->index, &type, &size); if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) { fail = SWITCH_TRUE; break; } ei_get_type(buf->buff, &buf->index, &type, &size); value = malloc(size + 1); if (ei_decode_string(buf->buff, &buf->index, value)) { fail = SWITCH_TRUE; break; } if (!fail && !strcmp(key, "body")) { switch_safe_free(event->body); event->body = value; } else if (!fail) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); } /* Do not free malloc here! The above commands utilize the raw allocated memory and skip any copying/duplication. Faster. */ } if (headerlength != i || fail) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { switch_event_fire(&event); ei_x_encode_atom(rbuf, "ok"); } } /* If the event wasn't successfully fired, or failed for any other reason, then make sure not to leak it. */ if ( event ) { switch_event_destroy(&event); } } } return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session, const char *function, const char *target, switch_media_bug_callback_t callback, void *user_data, time_t stop_time, switch_media_bug_flag_t flags, switch_media_bug_t **new_bug) { switch_media_bug_t *bug; //, *bp; switch_size_t bytes; switch_codec_implementation_t read_impl = { 0 }; switch_codec_implementation_t write_impl = { 0 }; switch_event_t *event; const char *p; if (!switch_channel_media_ready(session->channel)) { if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } } switch_core_session_get_read_impl(session, &read_impl); switch_core_session_get_write_impl(session, &write_impl); *new_bug = NULL; if ((p = switch_channel_get_variable(session->channel, "media_bug_answer_req")) && switch_true(p)) { flags |= SMBF_ANSWER_REQ; } #if 0 if (flags & SMBF_WRITE_REPLACE) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); switch_thread_rwlock_unlock(session->bug_rwlock); return SWITCH_STATUS_GENERR; } } switch_thread_rwlock_unlock(session->bug_rwlock); } if (flags & SMBF_READ_REPLACE) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_test_flag(bp, SMBF_READ_REPLACE)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); switch_thread_rwlock_unlock(session->bug_rwlock); return SWITCH_STATUS_GENERR; } } switch_thread_rwlock_unlock(session->bug_rwlock); } #endif if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) { return SWITCH_STATUS_MEMERR; } bug->callback = callback; bug->user_data = user_data; bug->session = session; bug->flags = flags; bug->function = "N/A"; bug->target = "N/A"; if (function) { bug->function = switch_core_session_strdup(session, function); } if (target) { bug->target = switch_core_session_strdup(session, target); } bug->stop_time = stop_time; bytes = read_impl.decoded_bytes_per_packet; if (!bug->flags) { bug->flags = (SMBF_READ_STREAM | SMBF_WRITE_STREAM); } if (switch_test_flag(bug, SMBF_READ_STREAM) || switch_test_flag(bug, SMBF_READ_PING)) { switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER); switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool); } bytes = write_impl.decoded_bytes_per_packet; if (switch_test_flag(bug, SMBF_WRITE_STREAM)) { switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER); switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool); } if ((bug->flags & SMBF_THREAD_LOCK)) { bug->thread_id = switch_thread_self(); } if (bug->callback) { switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT); if (result == SWITCH_FALSE) { switch_core_media_bug_destroy(bug); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n", switch_channel_get_name(session->channel)); return SWITCH_STATUS_GENERR; } } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel)); bug->ready = 1; switch_thread_rwlock_wrlock(session->bug_rwlock); bug->next = session->bugs; session->bugs = bug; switch_thread_rwlock_unlock(session->bug_rwlock); *new_bug = bug; if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_START) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target); switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } return SWITCH_STATUS_SUCCESS; }
static void *SWITCH_THREAD_FUNC api_exec(switch_thread_t *thread, void *obj) { switch_bool_t r = SWITCH_TRUE; struct api_command_struct *acs = (struct api_command_struct *) obj; switch_stream_handle_t stream = { 0 }; char *reply, *freply = NULL; switch_status_t status; if (!acs) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Internal error.\n"); return NULL; } if (!acs->listener || !acs->listener->rwlock || switch_thread_rwlock_tryrdlock(acs->listener->rwlock) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! cannot get read lock.\n"); goto done; } SWITCH_STANDARD_STREAM(stream); if ((status = switch_api_execute(acs->api_cmd, acs->arg, NULL, &stream)) == SWITCH_STATUS_SUCCESS) { reply = stream.data; } else { freply = switch_mprintf("%s: Command not found!\n", acs->api_cmd); reply = freply; r = SWITCH_FALSE; } if (!reply) { reply = "Command returned no output!"; r = SWITCH_FALSE; } if (*reply == '-') r = SWITCH_FALSE; if (acs->bg) { switch_event_t *event; if (switch_event_create(&event, SWITCH_EVENT_BACKGROUND_JOB) == SWITCH_STATUS_SUCCESS) { ei_x_buff ebuf; switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-UUID", acs->uuid_str); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command", acs->api_cmd); ei_x_new_with_version(&ebuf); if (acs->arg) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command-Arg", acs->arg); } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Successful", r ? "true" : "false"); switch_event_add_body(event, "%s", reply); switch_event_fire(&event); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending bgapi reply to %s\n", acs->pid.node); ei_x_encode_tuple_header(&ebuf, 3); if (r) ei_x_encode_atom(&ebuf, "bgok"); else ei_x_encode_atom(&ebuf, "bgerror"); _ei_x_encode_string(&ebuf, acs->uuid_str); _ei_x_encode_string(&ebuf, reply); switch_mutex_lock(acs->listener->sock_mutex); ei_send(acs->listener->sockfd, &acs->pid, ebuf.buff, ebuf.index); switch_mutex_unlock(acs->listener->sock_mutex); #ifdef EI_DEBUG ei_x_print_msg(&ebuf, &acs->pid, 1); #endif ei_x_free(&ebuf); } } else { ei_x_buff rbuf; ei_x_new_with_version(&rbuf); ei_x_encode_tuple_header(&rbuf, 2); if (!strlen(reply)) { reply = "Command returned no output!"; r = SWITCH_FALSE; } if (r) { ei_x_encode_atom(&rbuf, "ok"); } else { ei_x_encode_atom(&rbuf, "error"); } _ei_x_encode_string(&rbuf, reply); switch_mutex_lock(acs->listener->sock_mutex); ei_send(acs->listener->sockfd, &acs->pid, rbuf.buff, rbuf.index); switch_mutex_unlock(acs->listener->sock_mutex); #ifdef EI_DEBUG ei_x_print_msg(&rbuf, &acs->pid, 1); #endif ei_x_free(&rbuf); } switch_safe_free(stream.data); switch_safe_free(freply); if (acs->listener->rwlock) { switch_thread_rwlock_unlock(acs->listener->rwlock); } done: if (acs->bg) { switch_memory_pool_t *pool = acs->pool; acs = NULL; switch_core_destroy_memory_pool(&pool); pool = NULL; } return NULL; }
static int parse_exten(switch_event_t *event, switch_xml_t xexten, switch_event_t **extension) { switch_xml_t xcond, xaction, xexpression; char *exten_name = (char *) switch_xml_attr(xexten, "name"); int proceed = 0; char *expression_expanded = NULL, *field_expanded = NULL; switch_regex_t *re = NULL; const char *to = switch_event_get_header(event, "to"); const char *tzoff = NULL, *tzname = NULL; int offset = 0; check_tz(); if (!to) { to = "nobody"; } if (!exten_name) { exten_name = "_anon_"; } for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) { char *field = NULL; char *do_break_a = NULL; char *expression = NULL; const char *field_data = NULL; int ovector[30]; switch_bool_t anti_action = SWITCH_TRUE; break_t do_break_i = BREAK_ON_FALSE; int time_match; check_tz(); time_match = switch_xml_std_datetime_check(xcond, tzoff ? &offset : NULL, tzname); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); if (switch_xml_child(xcond, "condition")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Nested conditions are not allowed!\n"); proceed = 1; goto done; } field = (char *) switch_xml_attr(xcond, "field"); if ((xexpression = switch_xml_child(xcond, "expression"))) { expression = switch_str_nil(xexpression->txt); } else { expression = (char *) switch_xml_attr_soft(xcond, "expression"); } if ((expression_expanded = switch_event_expand_headers(event, expression)) == expression) { expression_expanded = NULL; } else { expression = expression_expanded; } if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) { if (!strcasecmp(do_break_a, "on-true")) { do_break_i = BREAK_ON_TRUE; } else if (!strcasecmp(do_break_a, "on-false")) { do_break_i = BREAK_ON_FALSE; } else if (!strcasecmp(do_break_a, "always")) { do_break_i = BREAK_ALWAYS; } else if (!strcasecmp(do_break_a, "never")) { do_break_i = BREAK_NEVER; } else { do_break_a = NULL; } } if (time_match == 1) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Date/Time Match (PASS) [%s] break=%s\n", to, exten_name, do_break_a ? do_break_a : "on-false"); anti_action = SWITCH_FALSE; } else if (time_match == 0) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Date/Time Match (FAIL) [%s] break=%s\n", to, exten_name, do_break_a ? do_break_a : "on-false"); } if (field) { if (strchr(field, '$')) { if ((field_expanded = switch_event_expand_headers(event, field)) == field) { field_expanded = NULL; field_data = field; } else { field_data = field_expanded; } } else { field_data = switch_event_get_header(event, field); } if (!field_data) { field_data = ""; } if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n", to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); anti_action = SWITCH_FALSE; } else { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n", to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); } } else if (time_match == -1) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Absolute Condition [%s]\n", to, exten_name); anti_action = SWITCH_FALSE; } if (anti_action) { for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) { const char *application = switch_xml_attr_soft(xaction, "application"); const char *loop = switch_xml_attr(xaction, "loop"); const char *data; const char *inline_ = switch_xml_attr_soft(xaction, "inline"); int xinline = switch_true(inline_); int loop_count = 1; if (!zstr(xaction->txt)) { data = xaction->txt; } else { data = (char *) switch_xml_attr_soft(xaction, "data"); } if (!*extension) { if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); abort(); } } if (loop) { loop_count = atoi(loop); } for (;loop_count > 0; loop_count--) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s ANTI-Action %s(%s) %s\n", to, application, data, xinline ? "INLINE" : ""); if (xinline) { switch_core_execute_chat_app(event, application, data); } else { switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, zstr(data) ? "__undef" : data); } } proceed = 1; } } else { if (field && strchr(expression, '(')) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "DP_MATCH", NULL); switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", switch_regex_set_event_header_callback, event); } for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) { char *application = (char *) switch_xml_attr_soft(xaction, "application"); const char *loop = switch_xml_attr(xaction, "loop"); char *data = NULL; char *substituted = NULL; uint32_t len = 0; char *app_data = NULL; const char *inline_ = switch_xml_attr_soft(xaction, "inline"); int xinline = switch_true(inline_); int loop_count = 1; if (!zstr(xaction->txt)) { data = xaction->txt; } else { data = (char *) switch_xml_attr_soft(xaction, "data"); } if (field && strchr(expression, '(')) { len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed; if (!(substituted = (char *) malloc(len))) { abort(); } memset(substituted, 0, len); switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector); app_data = substituted; } else { app_data = data; } if (!*extension) { if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); abort(); } } if (loop) { loop_count = atoi(loop); } for (;loop_count > 0; loop_count--) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s Action %s(%s) %s\n", to, application, app_data, xinline ? "INLINE" : ""); if (xinline) { switch_core_execute_chat_app(event, application, app_data); } else { switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, zstr(app_data) ? "__undef" : app_data); } } switch_safe_free(substituted); } } switch_regex_safe_free(re); if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) || (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) { break; } } done: switch_regex_safe_free(re); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); return proceed; }
static switch_status_t my_on_reporting(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_SUCCESS; char *values = NULL, *tmp = NULL, *pq_var = NULL; const char *var = NULL; cdr_field_t *cdr_field = NULL; switch_size_t len, offset; if (globals.shutdown) { return SWITCH_STATUS_SUCCESS; } if (!((globals.legs & CDR_LEG_A) && (globals.legs & CDR_LEG_B))) { if ((globals.legs & CDR_LEG_A)) { if (switch_channel_get_originator_caller_profile(channel)) { return SWITCH_STATUS_SUCCESS; } } else { if (switch_channel_get_originatee_caller_profile(channel)) { return SWITCH_STATUS_SUCCESS; } } } if (switch_dir_make_recursive(globals.spool_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.spool_dir); return SWITCH_STATUS_FALSE; } if (globals.debug) { switch_event_t *event; if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { char *buf; switch_channel_event_set_data(channel, event); switch_event_serialize(event, &buf, SWITCH_FALSE); switch_assert(buf); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "CHANNEL_DATA:\n%s\n", buf); switch_event_destroy(&event); switch_safe_free(buf); } } switch_zmalloc(values, 1); offset = 0; for (cdr_field = globals.db_schema->fields; cdr_field->var_name; cdr_field++) { if ((var = switch_channel_get_variable(channel, cdr_field->var_name))) { /* Allocate sufficient buffer for PQescapeString */ len = strlen(var); tmp = switch_core_session_alloc(session, len * 2 + 1); PQescapeString(tmp, var, len); var = tmp; } if (cdr_field->quote) { if ((cdr_field->not_null == SWITCH_FALSE) && zstr(var)) { pq_var = switch_mprintf("null,", var); } else { pq_var = switch_mprintf("'%s',", var); } } else { pq_var = switch_mprintf("%s,", var); } /* Resize values buffer to accomodate next var */ len = strlen(pq_var); tmp = realloc(values, offset + len); values = tmp; memcpy(values + offset, pq_var, len); switch_safe_free(pq_var); offset += len; } *(values + --offset) = '\0'; insert_cdr(values); switch_safe_free(values); return status; }
static int db_is_up(switch_odbc_handle_t *handle) { int ret = 0; SQLHSTMT stmt = NULL; SQLLEN m = 0; int result; switch_event_t *event; switch_odbc_status_t recon = 0; char *err_str = NULL; SQLCHAR sql[255] = ""; int max_tries = 120; int code = 0; SQLRETURN rc; SQLSMALLINT nresultcols; top: if (!handle) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Handle\n"); goto done; } if (handle->is_firebird) { strcpy((char *) sql, "select first 1 * from RDB$RELATIONS"); } else { strcpy((char *) sql, "select 1"); } if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) { code = __LINE__; goto error; } if (SQLPrepare(stmt, sql, SQL_NTS) != SQL_SUCCESS) { code = __LINE__; goto error; } result = SQLExecute(stmt); if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO) { code = __LINE__; goto error; } SQLRowCount(stmt, &m); rc = SQLNumResultCols(stmt, &nresultcols); if (rc != SQL_SUCCESS) { code = __LINE__; goto error; } ret = (int) nresultcols; /* determine statement type */ if (nresultcols <= 0) { /* statement is not a select statement */ code = __LINE__; goto error; } goto done; error: err_str = switch_odbc_handle_get_error(handle, stmt); recon = switch_odbc_handle_connect(handle); max_tries--; if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Failure-Message", "The sql server is not responding for DSN %s [%s][%d]", switch_str_nil(handle->dsn), switch_str_nil(err_str), code); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The sql server is not responding for DSN %s [%s][%d]\n", switch_str_nil(handle->dsn), switch_str_nil(err_str), code); if (recon == SWITCH_ODBC_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection has been re-established"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "The connection has been re-established\n"); } else { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The connection could not be re-established\n"); } if (!max_tries) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "Giving up!"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Giving up!\n"); } switch_event_fire(&event); } if (!max_tries) { goto done; } switch_safe_free(err_str); switch_yield(1000000); goto top; done: switch_safe_free(err_str); if (stmt) { SQLFreeHandle(SQL_HANDLE_STMT, stmt); } return ret; }
/** * Start execution of call sendfax component * @param call the call to send fax to * @param msg the original request * @param session_data the call's session */ static iks *start_sendfax_component(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { iks *iq = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; struct fax_component *sendfax_component = NULL; iks *sendfax = iks_find(iq, "sendfax"); iks *response = NULL; switch_event_t *execute_event = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_memory_pool_t *pool; iks *document; const char *fax_document; const char *fax_header; const char *fax_identity; const char *pages; /* validate attributes */ if (!VALIDATE_RAYO_SENDFAX(sendfax)) { return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST); } /* fax is only allowed if the call is not currently joined */ if (rayo_call_is_joined(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't send fax on a joined call"); } if (rayo_call_is_faxing(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress"); } /* get fax document */ document = iks_find(sendfax, "document"); if (!document) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "missing document"); } fax_document = iks_find_attrib_soft(document, "url"); if (zstr(fax_document)) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "missing document url"); } /* is valid URL type? */ if (!strncasecmp(fax_document, "http://", 7) || !strncasecmp(fax_document, "https://", 8)) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); /* need to fetch document from server... */ switch_api_execute("http_get", fax_document, session, &stream); if (!zstr(stream.data) && !strncmp(fax_document, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { fax_document = switch_core_session_strdup(session, stream.data); } else { switch_safe_free(stream.data); return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to fetch document"); } switch_safe_free(stream.data); } else if (!strncasecmp(fax_document, "file://", 7)) { fax_document = fax_document + 7; if (zstr(fax_document)) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid file:// url"); } } else if (strncasecmp(fax_document, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "unsupported url type"); } /* does document exist? */ if (switch_file_exists(fax_document, NULL) != SWITCH_STATUS_SUCCESS) { return iks_new_error_detailed_printf(iq, STANZA_ERROR_BAD_REQUEST, "file not found: %s", fax_document); } /* get fax identity and header */ fax_identity = iks_find_attrib_soft(document, "identity"); if (!zstr(fax_identity)) { switch_channel_set_variable(channel, "fax_ident", fax_identity); } else { switch_channel_set_variable(channel, "fax_ident", NULL); } fax_header = iks_find_attrib_soft(document, "header"); if (!zstr(fax_header)) { switch_channel_set_variable(channel, "fax_header", fax_header); } else { switch_channel_set_variable(channel, "fax_header", NULL); } /* get pages to send */ pages = iks_find_attrib_soft(document, "pages"); if (!zstr(pages)) { if (switch_regex_match(pages, "[1-9][0-9]*(-[1-9][0-9]*)?") == SWITCH_STATUS_FALSE) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid pages value"); } else { int start = 0; int end = 0; char *pages_dup = switch_core_session_strdup(session, pages); char *sep = strchr(pages_dup, '-'); if (sep) { *sep = '\0'; sep++; end = atoi(sep); } start = atoi(pages_dup); if (end && end < start) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid pages value"); } switch_channel_set_variable(channel, "fax_start_page", pages_dup); switch_channel_set_variable(channel, "fax_end_page", sep); } } else { switch_channel_set_variable(channel, "fax_start_page", NULL); switch_channel_set_variable(channel, "fax_end_page", NULL); } /* create sendfax component */ switch_core_new_memory_pool(&pool); sendfax_component = switch_core_alloc(pool, sizeof(*sendfax_component)); sendfax_component = FAX_COMPONENT(rayo_component_init((struct rayo_component *)sendfax_component, pool, RAT_CALL_COMPONENT, "sendfax", NULL, call, iks_find_attrib(iq, "from"))); if (!sendfax_component) { switch_core_destroy_memory_pool(&pool); return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "Failed to create sendfax entity"); } /* add channel variable so that fax component can be located from fax events */ switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(sendfax_component)); /* clear fax result variables */ switch_channel_set_variable(channel, "fax_success", NULL); switch_channel_set_variable(channel, "fax_result_code", NULL); switch_channel_set_variable(channel, "fax_result_text", NULL); switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL); switch_channel_set_variable(channel, "fax_document_total_pages", NULL); switch_channel_set_variable(channel, "fax_image_resolution", NULL); switch_channel_set_variable(channel, "fax_image_size", NULL); switch_channel_set_variable(channel, "fax_bad_rows", NULL); switch_channel_set_variable(channel, "fax_transfer_rate", NULL); switch_channel_set_variable(channel, "fax_ecm_used", NULL); switch_channel_set_variable(channel, "fax_local_station_id", NULL); switch_channel_set_variable(channel, "fax_remote_station_id", NULL); rayo_call_set_faxing(RAYO_CALL(call), 1); /* execute txfax APP */ if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "txfax"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", fax_document); if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); } if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to txfax (queue event failed)"); if (execute_event) { switch_event_destroy(&execute_event); } rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_RELEASE(sendfax_component); } else { /* component starting... */ rayo_component_send_start(RAYO_COMPONENT(sendfax_component), iq); } } else { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create txfax event"); rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_RELEASE(sendfax_component); } return response; }
void conference_event_pres_handler(switch_event_t *event) { char *to = switch_event_get_header(event, "to"); char *domain_name = NULL; char *dup_to = NULL, *conference_name, *dup_conference_name = NULL; conference_obj_t *conference; if (!to || strncasecmp(to, "conf+", 5) || !strchr(to, '@')) { return; } if (!(dup_to = strdup(to))) { return; } conference_name = dup_to + 5; if ((domain_name = strchr(conference_name, '@'))) { *domain_name++ = '\0'; } dup_conference_name = switch_mprintf("%q@%q", conference_name, domain_name); if ((conference = conference_find(conference_name, NULL)) || (conference = conference_find(dup_conference_name, NULL))) { if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", conference->name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", conference->name, conference->domain); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d caller%s)", conference->count, conference->count == 1 ? "" : "s"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", conference_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", conference->count == 1 ? "early" : "confirmed"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", conference->count == 1 ? "outbound" : "inbound"); switch_event_fire(&event); } switch_thread_rwlock_unlock(conference->rwlock); } else if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", CONF_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", conference_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", to); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Idle"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", conference_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound"); switch_event_fire(&event); } switch_safe_free(dup_to); switch_safe_free(dup_conference_name); }
abyss_bool handler_hook(TSession * r) { //char *mime = "text/html"; char buf[80] = "HTTP/1.1 200 OK\n"; switch_stream_handle_t stream = { 0 }; char *command; int i; TTableItem *ti; char *fs_user = NULL, *fs_domain = NULL; char *path_info = NULL; abyss_bool ret = TRUE; int html = 0, text = 0, xml = 0; const char *api_str; stream.data = r; stream.write_function = http_stream_write; stream.raw_write_function = http_stream_raw_write; if (!r || !r->requestInfo.uri) { return FALSE; } if ((command = strstr(r->requestInfo.uri, "/api/"))) { command += 5; } else if ((command = strstr(r->requestInfo.uri, "/webapi/"))) { command += 8; html++; } else if ((command = strstr(r->requestInfo.uri, "/txtapi/"))) { command += 8; text++; } else if ((command = strstr(r->requestInfo.uri, "/xmlapi/"))) { command += 8; xml++; } else { return FALSE; } if ((path_info = strchr(command, '/'))) { *path_info++ = '\0'; } for (i = 0; i < r->response_headers.size; i++) { ti = &r->response_headers.item[i]; if (!strcasecmp(ti->name, "freeswitch-user")) { fs_user = ti->value; } else if (!strcasecmp(ti->name, "freeswitch-domain")) { fs_domain = ti->value; } } if (is_authorized(r, command)) { goto auth; } ret = TRUE; goto end; auth: if (switch_event_create(&stream.param_event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) { const char *const content_length = RequestHeaderValue(r, "content-length"); if (html) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/html"); else if (text) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/plain"); else if (xml) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/xml"); if (fs_user) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user); if (fs_domain) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain); if (path_info) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info); switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-URI", r->requestInfo.uri); if (r->requestInfo.query) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", r->requestInfo.query); if (r->requestInfo.host) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-HOST", r->requestInfo.host); if (r->requestInfo.from) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-FROM", r->requestInfo.from); if (r->requestInfo.useragent) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", r->requestInfo.useragent); if (r->requestInfo.referer) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REFERER", r->requestInfo.referer); if (r->requestInfo.requestline) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", r->requestInfo.requestline); if (r->requestInfo.user) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER", r->requestInfo.user); if (r->requestInfo.port) switch_event_add_header(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", r->requestInfo.port); if (r->requestInfo.query || content_length) { char *q, *qd; char *next; char *query = (char *) r->requestInfo.query; char *name, *val; char qbuf[8192] = ""; if (r->requestInfo.method == m_post && content_length) { int len = atoi(content_length); int qlen = 0; if (len > 0) { int succeeded; char *qp = qbuf; do { int blen = r->conn->buffersize - r->conn->bufferpos; if ((qlen + blen) > len) { blen = len - qlen; } qlen += blen; if (qlen > sizeof(qbuf)) { break; } memcpy(qp, r->conn->buffer + r->conn->bufferpos, blen); qp += blen; if (qlen >= len) { break; } } while ((succeeded = ConnRead(r->conn, 2000))); query = qbuf; } } if (query) { switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query); qd = strdup(query); switch_assert(qd != NULL); q = qd; next = q; do { char *p; if ((next = strchr(next, '&'))) { *next++ = '\0'; } for (p = q; p && *p; p++) { if (*p == '+') { *p = ' '; } } switch_url_decode(q); name = q; if ((val = strchr(name, '='))) { *val++ = '\0'; switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, name, val); } q = next; } while (q != NULL); free(qd); } } } //ResponseChunked(r); //ResponseContentType(r, mime); //ResponseWrite(r); HTTPWrite(r, buf, (uint32_t) strlen(buf)); //HTTPWrite(r, "<pre>\n\n", 7); /* generation of the date field */ { const char *dateValue; DateToString(r->date, &dateValue); if (dateValue) { ResponseAddField(r, "Date", dateValue); } } /* Generation of the server field */ ResponseAddField(r, "Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc"); if (html) { ResponseAddField(r, "Content-Type", "text/html"); } else if (text) { ResponseAddField(r, "Content-Type", "text/plain"); } else if (xml) { ResponseAddField(r, "Content-Type", "text/xml"); } for (i = 0; i < r->response_headers.size; i++) { ti = &r->response_headers.item[i]; ConnWrite(r->conn, ti->name, (uint32_t) strlen(ti->name)); ConnWrite(r->conn, ": ", 2); ConnWrite(r->conn, ti->value, (uint32_t) strlen(ti->value)); ConnWrite(r->conn, CRLF, 2); } switch_snprintf(buf, sizeof(buf), "Connection: close\r\n"); ConnWrite(r->conn, buf, (uint32_t) strlen(buf)); if (html || text || xml) { ConnWrite(r->conn, "\r\n", 2); } if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) { command = "bgapi"; api_str = "unload mod_xml_rpc"; } else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) { command = "bgapi"; api_str = "reload mod_xml_rpc"; } else { api_str = r->requestInfo.query; } if (switch_api_execute(command, api_str, NULL, &stream) == SWITCH_STATUS_SUCCESS) { ResponseStatus(r, 200); r->responseStarted = TRUE; //r->done = TRUE; } else { ResponseStatus(r, 404); ResponseError(r); } //SocketClose(&(r->conn->socket)); HTTPWriteEnd(r); //if (r->conn->channelP) //ConnKill(r->conn); //ChannelInterrupt(r->conn->channelP); //ConnClose(r->conn); //ChannelDestroy(r->conn->channelP); r->requestInfo.keepalive = 0; end: return ret; }
void mtvm_menu_main(switch_core_session_t *session, vmivr_profile_t *profile) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_event_t *msg_list_params = NULL; size_t msg_count = 0; size_t current_msg = 1; size_t next_msg = current_msg; size_t previous_msg = current_msg; char *cmd = NULL; int retry; /* Different switch to control playback of phrases */ switch_bool_t initial_count_played = SWITCH_FALSE; switch_bool_t skip_header = SWITCH_FALSE; switch_bool_t msg_deleted = SWITCH_FALSE; switch_bool_t msg_undeleted = SWITCH_FALSE; switch_bool_t msg_saved = SWITCH_FALSE; vmivr_menu_profile_t menu = { "std_navigator" }; /* Initialize Menu Configs */ populate_profile_menu_event(profile, &menu); if (!menu.event_keys_dtmf || !menu.event_phrases) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases and Keys\n"); return; } /* Get VoiceMail List And update msg count */ cmd = switch_core_session_sprintf(session, "json %s %s %s", profile->api_profile, profile->domain, profile->id); msg_list_params = jsonapi2event(session, NULL, profile->api_msg_list, cmd); msg_count = atol(switch_event_get_header(msg_list_params,"VM-List-Count")); /* TODO Add Detection of new message and notify the user */ for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0; retry--) { dtmf_ss_t loc; char *dtmfa[16] = { 0 }; switch_event_t *phrase_params = NULL; switch_event_create(&phrase_params, SWITCH_EVENT_REQUEST_PARAMS); append_event_profile(phrase_params, profile, menu); populate_dtmfa_from_event(phrase_params, profile, menu, dtmfa); previous_msg = current_msg; /* Simple Protection to not go out of msg list scope */ /* TODO: Add Prompt to notify they reached the begining or the end */ if (next_msg == 0) { next_msg = 1; } else if (next_msg > msg_count) { next_msg = msg_count; } current_msg = next_msg; captureMenuInitialize(&loc, dtmfa); /* Prompt related to previous Message here */ append_event_message(session, profile, phrase_params, msg_list_params, previous_msg); if (msg_deleted) { msg_deleted = SWITCH_FALSE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "ack"), "deleted", phrase_params, NULL, 0); } if (msg_undeleted) { msg_undeleted = SWITCH_FALSE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "ack"), "undeleted", phrase_params, NULL, 0); } if (msg_saved) { msg_saved = SWITCH_FALSE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "ack"), "saved", phrase_params, NULL, 0); } /* Prompt related the current message */ append_event_message(session, profile, phrase_params, msg_list_params, current_msg); /* TODO check if msg is gone (purged by another session, notify user and auto jump to next message or something) */ if (!skip_header) { if (!initial_count_played) { cmd = switch_core_session_sprintf(session, "json %s %s %s", profile->api_profile, profile->domain, profile->id); jsonapi2event(session, phrase_params, profile->api_msg_count, cmd); initial_count_played = SWITCH_TRUE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "msg_count"), NULL, phrase_params, NULL, 0); } if (msg_count > 0) { captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "say_msg_number"), NULL, phrase_params, NULL, 0); captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "say_date"), NULL, phrase_params, NULL, 0); } } if (msg_count > 0) { /* TODO Update the Read date of a message (When msg start, or when it listen compleatly ??? To be determined */ captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "play_message"), NULL, phrase_params, NULL, 0); } skip_header = SWITCH_FALSE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, phrase_params, NULL, DEFAULT_IVR_TIMEOUT); if (loc.result == RES_TIMEOUT) { /* TODO Ask for the prompt Again IF retry != 0 */ } else if (loc.result == RES_INVALID) { /* TODO Say invalid option, and ask for the prompt again IF retry != 0 */ } else if (loc.result == RES_FOUND) { /* Matching DTMF Key Pressed */ const char *action = switch_event_get_header(menu.event_keys_dtmf, loc.dtmf_stored); /* Reset the try count */ retry = MAX_ATTEMPT; if (action) { if (!strcasecmp(action, "skip_intro")) { /* Skip Header / Play the recording again */ skip_header = SWITCH_TRUE; } else if (!strcasecmp(action, "next_msg")) { /* Next Message */ next_msg++; } else if (!strcasecmp(action, "prev_msg")) { /* Previous Message */ next_msg--; } else if (!strcasecmp(action, "delete_msg")) { /* Delete / Undelete Message */ if (strncasecmp(switch_event_get_header(phrase_params, "VM-Message-Flags"), "delete", 6)) { cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(phrase_params, "VM-Message-UUID")); mt_api_execute(session, profile->api_msg_delete, cmd); msg_deleted = SWITCH_TRUE; /* TODO Option for auto going to next message or just return to the menu (So user used to do 76 to delete and next message wont be confused) */ next_msg++; } else { cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(phrase_params, "VM-Message-UUID")); mt_api_execute(session, profile->api_msg_undelete, cmd); msg_undeleted = SWITCH_TRUE; } } else if (!strcasecmp(action, "save_msg")) { /* Save Message */ cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(phrase_params, "VM-Message-UUID")); mt_api_execute(session, profile->api_msg_save, cmd); msg_saved = SWITCH_TRUE; } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(action+5); if (fPtr) { fPtr(session, profile); } } else if (!strcasecmp(action, "return")) { /* Return */ retry = -1; } } } /* IF the API to get the message returned us a COPY of the file locally (temp file create from a DB or from a web server), delete it */ if (switch_true(switch_event_get_header(phrase_params, "VM-Message-Private-Local-Copy"))) { const char *file_path = switch_event_get_header(phrase_params, "VM-Message-File-Path"); if (file_path && unlink(file_path) != 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete temp file [%s]\n", file_path); } } switch_event_destroy(&phrase_params); } switch_event_destroy(&msg_list_params); free_profile_menu_event(&menu); return; }
void conference_event_call_setup_handler(switch_event_t *event) { switch_status_t status = SWITCH_STATUS_FALSE; conference_obj_t *conference = NULL; char *conf = switch_event_get_header(event, "Target-Component"); char *domain = switch_event_get_header(event, "Target-Domain"); char *dial_str = switch_event_get_header(event, "Request-Target"); char *dial_uri = switch_event_get_header(event, "Request-Target-URI"); char *action = switch_event_get_header(event, "Request-Action"); char *ext = switch_event_get_header(event, "Request-Target-Extension"); char *ext_domain = switch_event_get_header(event, "Request-Target-Domain"); char *full_url = switch_event_get_header(event, "full_url"); char *call_id = switch_event_get_header(event, "Request-Call-ID"); if (!ext) ext = dial_str; if (!zstr(conf) && !zstr(dial_str) && !zstr(action) && (conference = conference_find(conf, domain))) { switch_event_t *var_event; switch_event_header_t *hp; if (conference_utils_test_flag(conference, CFLAG_RFC4579)) { char *key = switch_mprintf("conference_%s_%s_%s_%s", conference->name, conference->domain, ext, ext_domain); char *expanded = NULL, *ostr = dial_str;; if (!strcasecmp(action, "call")) { if((conference->max_members > 0) && (conference->count >= conference->max_members)) { // Conference member limit has been reached; do not proceed with setup request status = SWITCH_STATUS_FALSE; } else { if (switch_event_create_plain(&var_event, SWITCH_EVENT_CHANNEL_DATA) != SWITCH_STATUS_SUCCESS) { abort(); } for(hp = event->headers; hp; hp = hp->next) { if (!strncasecmp(hp->name, "var_", 4)) { switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, hp->name + 4, hp->value); } } switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "conference_call_key", key); switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "conference_destination_number", ext); switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "conference_invite_uri", dial_uri); switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "conference_track_status", "true"); switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "conference_track_call_id", call_id); switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "sip_invite_domain", domain); switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "sip_invite_contact_params", "~isfocus"); if (!strncasecmp(ostr, "url+", 4)) { ostr += 4; } else if (!switch_true(full_url) && conference->outcall_templ) { if ((expanded = switch_event_expand_headers(var_event, conference->outcall_templ))) { ostr = expanded; } } status = conference_outcall_bg(conference, NULL, NULL, ostr, 60, NULL, NULL, NULL, NULL, NULL, NULL, &var_event); if (expanded && expanded != conference->outcall_templ) { switch_safe_free(expanded); } } } else if (!strcasecmp(action, "end")) { if (switch_core_session_hupall_matching_var("conference_call_key", key, SWITCH_CAUSE_NORMAL_CLEARING)) { conference_send_notify(conference, "SIP/2.0 200 OK\r\n", call_id, SWITCH_TRUE); } else { conference_send_notify(conference, "SIP/2.0 481 Failure\r\n", call_id, SWITCH_TRUE); } status = SWITCH_STATUS_SUCCESS; } switch_safe_free(key); } else { // Conference found but doesn't support referral. status = SWITCH_STATUS_FALSE; } switch_thread_rwlock_unlock(conference->rwlock); } else { // Couldn't find associated conference. Indicate failure on refer subscription status = SWITCH_STATUS_FALSE; } if(status != SWITCH_STATUS_SUCCESS) { // Unable to setup call, need to generate final NOTIFY if (switch_event_create(&event, SWITCH_EVENT_CONFERENCE_DATA) == SWITCH_STATUS_SUCCESS) { event->flags |= EF_UNIQ_HEADERS; switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "conference-name", conf); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "conference-domain", domain); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "conference-event", "refer"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call_id", call_id); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "final", "true"); switch_event_add_body(event, "%s", "SIP/2.0 481 Failure\r\n"); switch_event_fire(&event); } } }
switch_status_t mtvm_menu_record(switch_core_session_t *session, vmivr_profile_t *profile, vmivr_menu_profile_t menu, const char *file_name) { switch_status_t status = SWITCH_STATUS_FALSE; switch_channel_t *channel = switch_core_session_get_channel(session); int retry; switch_bool_t record_prompt = SWITCH_TRUE; switch_bool_t listen_recording = SWITCH_FALSE; switch_bool_t play_instruction = SWITCH_TRUE; if (!menu.event_keys_dtmf || !menu.event_phrases) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases and Keys\n"); return status; } for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0; retry--) { dtmf_ss_t loc; char *dtmfa[16] = { 0 }; switch_event_t *phrase_params = NULL; switch_file_handle_t fh = { 0 }; /* TODO Make the following configurable */ fh.thresh = 200; fh.silence_hits = 4; //fh.samplerate = 8000; switch_event_create(&phrase_params, SWITCH_EVENT_REQUEST_PARAMS); append_event_profile(phrase_params, profile, menu); populate_dtmfa_from_event(phrase_params, profile, menu, dtmfa); captureMenuInitialize(&loc, dtmfa); if (record_prompt) { if (play_instruction) { captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "instructions"), NULL, phrase_params, NULL, 0); } play_instruction = SWITCH_TRUE; captureMenuRecord(session, &loc, phrase_params, file_name, &fh, 30 /* TODO Make max recording configurable */); } else { if (listen_recording) { switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, "VM-Record-File-Path", "%s", file_name); captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "play_recording"), NULL, phrase_params, NULL, 0); listen_recording = SWITCH_FALSE; } captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, phrase_params, NULL, DEFAULT_IVR_TIMEOUT); } if (loc.recorded_audio) { /* Reset the try count */ retry = MAX_ATTEMPT; /* TODO Check if message is too short */ record_prompt = SWITCH_FALSE; } else if (loc.result == RES_TIMEOUT) { /* TODO Ask for the prompt Again IF retry != 0 */ } else if (loc.result == RES_INVALID) { /* TODO Say invalid option, and ask for the prompt again IF retry != 0 */ } else if (loc.result == RES_FOUND) { /* Matching DTMF Key Pressed */ const char *action = switch_event_get_header(menu.event_keys_dtmf, loc.dtmf_stored); /* Reset the try count */ retry = MAX_ATTEMPT; if (action) { if (!strcasecmp(action, "listen")) { /* Listen */ listen_recording = SWITCH_TRUE; } else if (!strcasecmp(action, "save")) { retry = -1; /* TODO ALLOW SAVE ONLY IF FILE IS RECORDED AND HIGHER THAN MIN SIZE */ status = SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(action, "rerecord")) { record_prompt = SWITCH_TRUE; } else if (!strcasecmp(action, "skip_instruction")) { /* Skip Recording Greeting */ play_instruction = SWITCH_FALSE; } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(action+5); if (fPtr) { fPtr(session, profile); } } else if (!strcasecmp(action, "return")) { /* Return */ retry = -1; } } } switch_event_destroy(&phrase_params); } return status; }
SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) { switch_io_event_hook_read_frame_t *ptr; switch_status_t status = SWITCH_STATUS_FALSE; int need_codec, perfect, do_bugs = 0, do_resample = 0, is_cng = 0; switch_codec_implementation_t codec_impl; unsigned int flag = 0; switch_assert(session != NULL); if (switch_mutex_trylock(session->codec_read_mutex) == SWITCH_STATUS_SUCCESS) { switch_mutex_unlock(session->codec_read_mutex); } else { switch_cond_next(); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_SUCCESS; } if (!(session->read_codec && session->read_codec->implementation && switch_core_codec_ready(session->read_codec))) { if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_get_state(session->channel) == CS_HIBERNATE) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s reading on a session with no media!\n", switch_channel_get_name(session->channel)); switch_cond_next(); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_SUCCESS; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->codec_read_mutex); if (!switch_core_codec_ready(session->read_codec)) { switch_mutex_unlock(session->codec_read_mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->read_codec->mutex); top: if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { switch_ivr_dmachine_ping(session->dmachine, NULL); } if (switch_channel_down(session->channel) || !switch_core_codec_ready(session->read_codec)) { *frame = NULL; status = SWITCH_STATUS_FALSE; goto even_more_done; } status = SWITCH_STATUS_FALSE; need_codec = perfect = 0; *frame = NULL; if (session->read_codec && !session->track_id && session->track_duration) { if (session->read_frame_count == 0) { switch_event_t *event; session->read_frame_count = (session->read_impl.actual_samples_per_second / session->read_impl.samples_per_packet) * session->track_duration; switch_event_create(&event, SWITCH_EVENT_SESSION_HEARTBEAT); switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } else { session->read_frame_count--; } } if (switch_channel_test_flag(session->channel, CF_HOLD)) { switch_yield(session->read_impl.microseconds_per_packet); status = SWITCH_STATUS_BREAK; goto even_more_done; } if (session->endpoint_interface->io_routines->read_frame) { switch_mutex_unlock(session->read_codec->mutex); switch_mutex_unlock(session->codec_read_mutex); if ((status = session->endpoint_interface->io_routines->read_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) { for (ptr = session->event_hooks.read_frame; ptr; ptr = ptr->next) { if ((status = ptr->read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) { break; } } } if (!SWITCH_READ_ACCEPTABLE(status) || !session->read_codec || !switch_core_codec_ready(session->read_codec)) { *frame = NULL; return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->codec_read_mutex); if (!switch_core_codec_ready(session->read_codec)) { switch_mutex_unlock(session->codec_read_mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->read_codec->mutex); if (!switch_core_codec_ready(session->read_codec)) { *frame = NULL; status = SWITCH_STATUS_FALSE; goto even_more_done; } } if (status != SWITCH_STATUS_SUCCESS) { goto done; } if (!(*frame)) { goto done; } 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 && !session->plc) { goto done; } is_cng = 1; } switch_assert((*frame)->codec != NULL); if (!(session->read_codec && (*frame)->codec && (*frame)->codec->implementation) && switch_core_codec_ready((*frame)->codec)) { status = SWITCH_STATUS_FALSE; goto done; } codec_impl = *(*frame)->codec->implementation; if (session->read_codec->implementation->impl_id != codec_impl.impl_id) { need_codec = TRUE; } if (codec_impl.actual_samples_per_second != session->read_impl.actual_samples_per_second) { do_resample = 1; } if (session->bugs && !need_codec) { do_bugs = 1; need_codec = 1; } if (switch_test_flag(session, SSF_READ_TRANSCODE) && !need_codec && switch_core_codec_ready(session->read_codec)) { switch_core_session_t *other_session; const char *uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE); switch_clear_flag(session, SSF_READ_TRANSCODE); if (uuid && (other_session = switch_core_session_locate(uuid))) { switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_WRITE_CODEC_RESET); switch_core_session_rwunlock(other_session); } } if (switch_test_flag(session, SSF_READ_CODEC_RESET)) { switch_core_codec_reset(session->read_codec); switch_clear_flag(session, SSF_READ_CODEC_RESET); } if (status == SWITCH_STATUS_SUCCESS && need_codec) { switch_frame_t *enc_frame, *read_frame = *frame; switch_set_flag(session, SSF_READ_TRANSCODE); if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) { switch_core_session_message_t msg = { 0 }; msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY; switch_core_session_receive_message(session, &msg); switch_set_flag(session, SSF_WARN_TRANSCODE); } if (read_frame->codec || is_cng) { session->raw_read_frame.datalen = session->raw_read_frame.buflen; if (is_cng) { if (session->plc) { plc_fillin(session->plc, session->raw_read_frame.data, read_frame->codec->implementation->decoded_bytes_per_packet / 2); is_cng = 0; flag &= !SFF_CNG; } else { memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet); } session->raw_read_frame.timestamp = 0; session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); read_frame = &session->raw_read_frame; status = SWITCH_STATUS_SUCCESS; } else { switch_codec_t *use_codec = read_frame->codec; if (do_bugs) { switch_thread_rwlock_wrlock(session->bug_rwlock); if (!session->bugs) { do_bugs = 0; switch_thread_rwlock_unlock(session->bug_rwlock); goto done; } if (!switch_core_codec_ready(&session->bug_codec)) { switch_core_codec_copy(read_frame->codec, &session->bug_codec, NULL); } use_codec = &session->bug_codec; switch_thread_rwlock_unlock(session->bug_rwlock); switch_thread_rwlock_wrlock(session->bug_rwlock); if (!session->bugs) { do_bugs = 0; } switch_thread_rwlock_unlock(session->bug_rwlock); if (!do_bugs) goto done; } if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen); status = SWITCH_STATUS_SUCCESS; } else { switch_thread_rwlock_rdlock(session->bug_rwlock); status = switch_core_codec_decode(use_codec->implementation?use_codec:read_frame->codec, session->read_codec, read_frame->data, read_frame->datalen, session->read_impl.actual_samples_per_second, session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate, &read_frame->flags); switch_thread_rwlock_unlock(session->bug_rwlock); } if (status == SWITCH_STATUS_SUCCESS) { if ((switch_channel_test_flag(session->channel, CF_JITTERBUFFER) || switch_channel_test_flag(session->channel, CF_CNG_PLC)) && !session->plc) { session->plc = plc_init(NULL); } if (session->plc) { if (switch_test_flag(read_frame, SFF_PLC)) { plc_fillin(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2); switch_clear_flag(read_frame, SFF_PLC); } else { plc_rx(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2); } } } } if (do_resample && ((status == SWITCH_STATUS_SUCCESS) || is_cng)) { status = SWITCH_STATUS_RESAMPLE; } switch (status) { case SWITCH_STATUS_RESAMPLE: if (!session->read_resampler) { switch_mutex_lock(session->resample_mutex); status = switch_resample_create(&session->read_resampler, read_frame->codec->implementation->actual_samples_per_second, session->read_impl.actual_samples_per_second, session->read_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1); switch_mutex_unlock(session->resample_mutex); if (status != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to allocate resampler\n"); status = SWITCH_STATUS_FALSE; goto done; } } case SWITCH_STATUS_SUCCESS: session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); session->raw_read_frame.rate = read_frame->rate; if (read_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) { session->raw_read_frame.timestamp = 0; } else { session->raw_read_frame.timestamp = read_frame->timestamp; } session->raw_read_frame.ssrc = read_frame->ssrc; session->raw_read_frame.seq = read_frame->seq; session->raw_read_frame.m = read_frame->m; session->raw_read_frame.payload = read_frame->payload; session->raw_read_frame.flags = 0; if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.flags |= SFF_PLC; } read_frame = &session->raw_read_frame; break; case SWITCH_STATUS_NOOP: if (session->read_resampler) { switch_mutex_lock(session->resample_mutex); switch_resample_destroy(&session->read_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating read resampler\n"); switch_mutex_unlock(session->resample_mutex); } status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_BREAK: memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet); session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); session->raw_read_frame.timestamp = read_frame->timestamp; session->raw_read_frame.rate = read_frame->rate; session->raw_read_frame.ssrc = read_frame->ssrc; session->raw_read_frame.seq = read_frame->seq; session->raw_read_frame.m = read_frame->m; session->raw_read_frame.payload = read_frame->payload; session->raw_read_frame.flags = 0; if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.flags |= SFF_PLC; } read_frame = &session->raw_read_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); goto done; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n", session->read_codec->codec_interface->interface_name); goto done; } } if (session->bugs) { switch_media_bug_t *bp; switch_bool_t ok = SWITCH_TRUE; int prune = 0; switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) { continue; } if (switch_test_flag(bp, SMBF_PRUNE)) { prune++; continue; } if (bp->ready && switch_test_flag(bp, SMBF_READ_STREAM)) { switch_mutex_lock(bp->read_mutex); switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen); if (bp->callback) { ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ); } switch_mutex_unlock(bp->read_mutex); } if (ok && switch_test_flag(bp, SMBF_READ_REPLACE)) { do_bugs = 0; if (bp->callback) { bp->read_replace_frame_in = read_frame; bp->read_replace_frame_out = read_frame; if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_REPLACE)) == SWITCH_TRUE) { read_frame = bp->read_replace_frame_out; } } } if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) { switch_set_flag(bp, SMBF_PRUNE); prune++; } } switch_thread_rwlock_unlock(session->bug_rwlock); if (prune) { switch_core_media_bug_prune(session); } } if (do_bugs) { goto done; } if (session->read_codec) { if (session->read_resampler) { short *data = read_frame->data; switch_mutex_lock(session->resample_mutex); switch_resample_process(session->read_resampler, data, (int) read_frame->datalen / 2); memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2); read_frame->samples = session->read_resampler->to_len; read_frame->datalen = session->read_resampler->to_len * 2; read_frame->rate = session->read_resampler->to_rate; switch_mutex_unlock(session->resample_mutex); } if (read_frame->datalen == session->read_impl.decoded_bytes_per_packet) { perfect = TRUE; } else { if (!session->raw_read_buffer) { switch_size_t bytes = session->read_impl.decoded_bytes_per_packet; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Engaging Read Buffer at %u bytes vs %u\n", (uint32_t) bytes, (uint32_t) (*frame)->datalen); switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0); } if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) { status = SWITCH_STATUS_MEMERR; goto done; } } if (perfect || switch_buffer_inuse(session->raw_read_buffer) >= session->read_impl.decoded_bytes_per_packet) { if (perfect) { enc_frame = read_frame; session->raw_read_frame.rate = read_frame->rate; } else { session->raw_read_frame.datalen = (uint32_t) switch_buffer_read(session->raw_read_buffer, session->raw_read_frame.data, session->read_impl.decoded_bytes_per_packet); session->raw_read_frame.rate = session->read_impl.actual_samples_per_second; enc_frame = &session->raw_read_frame; } session->enc_read_frame.datalen = session->enc_read_frame.buflen; switch_assert(session->read_codec != NULL); switch_assert(enc_frame != NULL); switch_assert(enc_frame->data != NULL); status = switch_core_codec_encode(session->read_codec, enc_frame->codec, enc_frame->data, enc_frame->datalen, session->read_impl.actual_samples_per_second, session->enc_read_frame.data, &session->enc_read_frame.datalen, &session->enc_read_frame.rate, &flag); switch (status) { case SWITCH_STATUS_RESAMPLE: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 1\n"); case SWITCH_STATUS_SUCCESS: session->enc_read_frame.samples = session->read_impl.decoded_bytes_per_packet / sizeof(int16_t); if (perfect) { if (enc_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) { session->enc_read_frame.timestamp = 0; } else { session->enc_read_frame.timestamp = read_frame->timestamp; } session->enc_read_frame.rate = read_frame->rate; session->enc_read_frame.ssrc = read_frame->ssrc; session->enc_read_frame.seq = read_frame->seq; session->enc_read_frame.m = read_frame->m; session->enc_read_frame.payload = session->read_impl.ianacode; } *frame = &session->enc_read_frame; break; case SWITCH_STATUS_NOOP: session->raw_read_frame.samples = enc_frame->codec->implementation->samples_per_packet; session->raw_read_frame.timestamp = read_frame->timestamp; session->raw_read_frame.payload = enc_frame->codec->implementation->ianacode; session->raw_read_frame.m = read_frame->m; session->raw_read_frame.ssrc = read_frame->ssrc; session->raw_read_frame.seq = read_frame->seq; *frame = enc_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); *frame = NULL; status = SWITCH_STATUS_GENERR; break; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n", session->read_codec->codec_interface->interface_name); *frame = NULL; status = SWITCH_STATUS_GENERR; break; } } else { goto top; } } } done: if (!(*frame)) { status = SWITCH_STATUS_FALSE; } else { if (flag & SFF_CNG) { switch_set_flag((*frame), SFF_CNG); } if (session->bugs) { switch_media_bug_t *bp; switch_bool_t ok = SWITCH_TRUE; int prune = 0; switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) { continue; } if (switch_test_flag(bp, SMBF_PRUNE)) { prune++; continue; } if (bp->ready && switch_test_flag(bp, SMBF_READ_PING)) { switch_mutex_lock(bp->read_mutex); if (bp->callback) { if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_PING) == SWITCH_FALSE || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) { ok = SWITCH_FALSE; } } switch_mutex_unlock(bp->read_mutex); } if (ok == SWITCH_FALSE) { switch_set_flag(bp, SMBF_PRUNE); prune++; } } switch_thread_rwlock_unlock(session->bug_rwlock); if (prune) { switch_core_media_bug_prune(session); } } } even_more_done: if (!*frame || !(*frame)->codec || !(*frame)->codec->implementation || !switch_core_codec_ready((*frame)->codec)) { *frame = &runtime.dummy_cng_frame; } switch_mutex_unlock(session->read_codec->mutex); switch_mutex_unlock(session->codec_read_mutex); return status; }
static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1]; int headerlength; if (ei_decode_string_or_binary(buf->buff, &buf->index, SWITCH_UUID_FORMATTED_LENGTH, uuid) || ei_decode_list_header(buf->buff, &buf->index, &headerlength)) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { switch_core_session_t *session; if (!zstr_buf(uuid) && (session = switch_core_session_locate(uuid))) { switch_event_t *event; if (switch_event_create(&event, SWITCH_EVENT_SEND_MESSAGE) == SWITCH_STATUS_SUCCESS) { char key[1024]; char *value; int type; int size; int i = 0; switch_bool_t fail = SWITCH_FALSE; while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; ei_get_type(buf->buff, &buf->index, &type, &size); if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) { fail = SWITCH_TRUE; break; } ei_get_type(buf->buff, &buf->index, &type, &size); value = malloc(size + 1); if (ei_decode_string(buf->buff, &buf->index, value)) { fail = SWITCH_TRUE; break; } if (!fail) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); } } if (headerlength != i || fail) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); switch_event_destroy(&event); } else { if (switch_core_session_queue_private_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { ei_x_encode_atom(rbuf, "ok"); } else { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badmem"); switch_event_destroy(&event); } } } /* release the lock returned by session locate */ switch_core_session_rwunlock(session); } else { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "nosession"); } } return SWITCH_STATUS_SUCCESS; }
static abyss_bool user_attributes(const char *user, const char *domain_name, const char **ppasswd, const char **pvm_passwd, const char **palias, const char **pallowed_commands) { const char *passwd; const char *vm_passwd; const char *alias; const char *allowed_commands; switch_event_t *params; switch_xml_t x_user, x_params, x_param; passwd = NULL; vm_passwd = NULL; alias = NULL; allowed_commands = NULL; if (ppasswd) *ppasswd = NULL; if (pvm_passwd) *pvm_passwd = NULL; if (palias) *palias = NULL; if (pallowed_commands) *pallowed_commands = NULL; params = NULL; switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); switch_assert(params); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "number_alias", "check"); if (switch_xml_locate_user_merged("id", user, domain_name, NULL, &x_user, params) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(¶ms); return FALSE; } switch_event_destroy(¶ms); alias = switch_xml_attr(x_user, "number-alias"); if ((x_params = switch_xml_child(x_user, "params"))) { for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) { const char *var = switch_xml_attr_soft(x_param, "name"); const char *val = switch_xml_attr_soft(x_param, "value"); if (!strcasecmp(var, "password")) { passwd = val; } else if (!strcasecmp(var, "vm-password")) { vm_passwd = val; } else if (!strcasecmp(var, "http-allowed-api")) { allowed_commands = val; } } } if (ppasswd && passwd) { *ppasswd = strdup(passwd); } if (pvm_passwd && vm_passwd) { *pvm_passwd = strdup(vm_passwd); } if (palias && alias) { *palias = strdup(alias); } if (pallowed_commands && allowed_commands) { *pallowed_commands = strdup(allowed_commands); } if (x_user) { switch_xml_free(x_user); } return TRUE; }
SWITCH_DECLARE(switch_status_t) switch_core_session_set_real_read_codec(switch_core_session_t *session, switch_codec_t *codec) { switch_event_t *event; switch_channel_t *channel = switch_core_session_get_channel(session); char tmp[30]; switch_status_t status = SWITCH_STATUS_SUCCESS; int changed_read_codec = 0; switch_mutex_lock(session->codec_read_mutex); if (codec && (!codec->implementation || !switch_core_codec_ready(codec))) { codec = NULL; } if (codec) { /* set real_read_codec and read_codec */ if (!session->real_read_codec) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Original read codec set to %s:%d\n", switch_channel_get_name(session->channel), codec->implementation->iananame, codec->implementation->ianacode); session->read_codec = session->real_read_codec = codec; changed_read_codec = 1; if (codec->implementation) { session->read_impl = *codec->implementation; session->real_read_impl = *codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } } else { /* replace real_read_codec */ switch_codec_t *cur_codec; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Original read codec replaced with %s:%d\n", switch_channel_get_name(session->channel), codec->implementation->iananame, codec->implementation->ianacode); /* Set real_read_codec to front of the list of read_codecs */ cur_codec = session->read_codec; while (cur_codec != NULL) { if (cur_codec->next == session->real_read_codec) { cur_codec->next = codec; break; } cur_codec = cur_codec->next; } session->real_read_codec = codec; /* set read_codec with real_read_codec if it no longer is ready */ if (!switch_core_codec_ready(session->read_codec)) { session->read_codec = codec; changed_read_codec = 1; if (codec->implementation) { session->read_impl = *codec->implementation; session->real_read_impl = *codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } } } /* force media bugs to copy the read codec from the next frame */ switch_thread_rwlock_wrlock(session->bug_rwlock); if (switch_core_codec_ready(&session->bug_codec)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Destroying BUG Codec %s:%d\n", session->bug_codec.implementation->iananame, session->bug_codec.implementation->ianacode); switch_core_codec_destroy(&session->bug_codec); } switch_thread_rwlock_unlock(session->bug_rwlock); } else { status = SWITCH_STATUS_FALSE; goto end; } if (changed_read_codec && session->read_codec && session->read_impl.decoded_bytes_per_packet) { if (switch_event_create(&event, SWITCH_EVENT_CODEC) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second); if (session->read_impl.actual_samples_per_second != session->read_impl.samples_per_second) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second); } switch_event_fire(&event); } switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame); switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second); switch_channel_set_variable(channel, "read_rate", tmp); session->raw_read_frame.codec = session->read_codec; session->raw_write_frame.codec = session->read_codec; session->enc_read_frame.codec = session->read_codec; session->enc_write_frame.codec = session->read_codec; } end: if (session->read_codec) { switch_channel_set_flag(channel, CF_MEDIA_SET); } switch_mutex_unlock(session->codec_read_mutex); return status; }
abyss_bool handler_hook(TSession * r) { switch_stream_handle_t stream = { 0 }; char *command; int i; char *fs_user = NULL, *fs_domain = NULL; char *path_info = NULL; abyss_bool ret = TRUE; int html = 0, text = 0, xml = 0, api = 0; const char *api_str; const char *uri = 0; TRequestInfo *info = 0; switch_event_t *evnt = 0; /* shortcut to stream.param_event */ if (!r || !(info = &r->requestInfo) || !(uri = info->uri)) { return FALSE; } stream.data = r; stream.write_function = http_stream_write; stream.raw_write_function = http_stream_raw_write; if ((command = strstr(uri, "/api/"))) { command += 5; api++; } else if ((command = strstr(uri, "/webapi/"))) { command += 8; html++; } else if ((command = strstr(uri, "/txtapi/"))) { command += 8; text++; } else if ((command = strstr(uri, "/xmlapi/"))) { command += 8; xml++; } else { return FALSE; /* 404 */ } if ((path_info = strchr(command, '/'))) { *path_info++ = '\0'; } for (i = 0; i < r->responseHeaderFields.size; i++) { TTableItem *ti = &r->responseHeaderFields.item[i]; if (!strcasecmp(ti->name, "freeswitch-user")) { fs_user = ti->value; } else if (!strcasecmp(ti->name, "freeswitch-domain")) { fs_domain = ti->value; } } if (!is_authorized(r, command)) { ret = TRUE; goto end; } /* auth: */ if (switch_event_create(&stream.param_event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) { const char *const content_length = RequestHeaderValue(r, "content-length"); evnt = stream.param_event; if (html) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/html"); } else if (text) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/plain"); } else if (xml) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/xml"); } if (api) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-API", "api"); } if (fs_user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user); if (fs_domain) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain); if (path_info) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info); if (info->host) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-HOST", info->host); if (info->from) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-FROM", info->from); if (info->useragent) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", info->useragent); if (info->referer) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REFERER", info->referer); if (info->requestline) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", info->requestline); if (info->user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER", info->user); if (info->port) switch_event_add_header(evnt, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", info->port); { char *q, *qd; char *next; char *query = (char *) info->query; char *name, *val; char qbuf[8192] = ""; /* first finish reading from the socket if post method was used*/ if (info->method == m_post && content_length) { int len = atoi(content_length); int qlen = 0; if (len > 0) { int succeeded = TRUE; char *qp = qbuf; char *readError; do { int blen = r->connP->buffersize - r->connP->bufferpos; if ((qlen + blen) > len) { blen = len - qlen; } qlen += blen; if (qlen > sizeof(qbuf)) { break; } memcpy(qp, r->connP->buffer.b + r->connP->bufferpos, blen); qp += blen; if (qlen >= len) { break; } ConnRead(r->connP, 2000, NULL, NULL, &readError); if (readError) { succeeded = FALSE; free(readError); } } while (succeeded); query = qbuf; } } /* parse query and add kv-pairs as event headers */ /* a kv pair starts with '&', '+' or \0 mark the end */ if (query) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query); qd = strdup(query); } else { qd = strdup(uri); } switch_assert(qd != NULL); q = qd; next = q; do { char *p; if (next = strchr(next, '&')) { if (!query) { /* pass kv pairs from uri to query */ /* "?" is absent in url so parse uri */ *((char *)uri + (next - q - 1)) = '\0'; query = next; switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", next); /* and strip uri */ /* the start of first kv pair marks the end of uri */ /* to prevent kv-pairs confusing fs api commands */ /* that have arguments separated by space */ } *next++ = '\0'; } for (p = q; p && *p; p++) { if (*p == '+') { *p = ' '; } } /* hmmm, get method requests are already decoded ... */ switch_url_decode(q); name = q; if ((val = strchr(name, '='))) { *val++ = '\0'; switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, name, val); } q = next; } while (q != NULL); free(qd); } } switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-URI", uri); /* We made it this far, always OK */ if (!HTTPWrite(r, "HTTP/1.1 200 OK\r\n", (uint32_t) strlen("HTTP/1.1 200 OK\r\n"))) { return TRUE; } ResponseAddField(r, "Connection", "close"); /* generation of the date field */ if (evnt) { ResponseAddField(r, "Date", switch_event_get_header(evnt, "Event-Date-GMT")); } else { const char *dateValue; DateToString(r->date, &dateValue); if (dateValue) { ResponseAddField(r, "Date", dateValue); free((void *)dateValue); } } /* Generation of the server field */ ResponseAddField(r, "Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc"); if (html) { ResponseAddField(r, "Content-Type", "text/html"); } else if (text) { ResponseAddField(r, "Content-Type", "text/plain"); } else if (xml) { ResponseAddField(r, "Content-Type", "text/xml"); } for (i = 0; i < r->responseHeaderFields.size; i++) { TTableItem *ti = &r->responseHeaderFields.item[i]; char *header = switch_mprintf("%s: %s\r\n", ti->name, ti->value); if (!ConnWrite(r->connP, header, (uint32_t) strlen(header))) { switch_safe_free(header); return TRUE; } switch_safe_free(header); } /* send end http header */ if (html||text||xml) { if (!ConnWrite(r->connP, CRLF, 2)) { return TRUE; } } else { /* content-type and end of http header will be streamed by fs api or http_stream_write */ } if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", info->query)) { command = "bgapi"; api_str = "unload mod_xml_rpc"; } else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", info->query)) { command = "bgapi"; api_str = "reload mod_xml_rpc"; } else { api_str = info->query; } /* TODO (maybe): take "refresh=xxx" out of query as to not confuse fs api commands */ /* execute actual fs api command */ /* fs api command will write to stream, calling http_stream_write / http_stream_raw_write */ /* switch_api_execute will stream INVALID COMMAND before it fails */ switch_api_execute(command, api_str, NULL, &stream); r->responseStarted = TRUE; ResponseStatus(r, 200); /* we don't want an assertion failure */ r->requestInfo.keepalive = 0; end: return ret; }
vmivr_profile_t *get_profile(switch_core_session_t *session, const char *profile_name) { vmivr_profile_t *profile = NULL; switch_xml_t cfg, xml, x_profiles, x_profile, x_apis, x_settings, param; if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf); return profile; } if (!(x_profiles = switch_xml_child(cfg, "profiles"))) { goto end; } if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile_name))) { if (!(profile = switch_core_session_alloc(session, sizeof(vmivr_profile_t)))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Alloc Failure\n"); goto end; } profile->name = profile_name; profile->current_msg = 0; profile->current_msg_uuid = NULL; profile->folder_name = VM_FOLDER_ROOT; profile->folder_filter = VM_MSG_NOT_READ; /* TODO Make the following configurable */ profile->api_profile = profile->name; profile->menu_check_auth = "std_authenticate"; profile->menu_check_main = "std_main_menu"; profile->menu_check_terminate = "std_purge"; /* Populate default general settings */ switch_event_create(&profile->event_settings, SWITCH_EVENT_REQUEST_PARAMS); switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "IVR-Maximum-Attempts", "%d", 3); switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "IVR-Entry-Timeout", "%d", 3000); switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Exit-Purge", "%s", "true"); switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Password-Mask", "%s", "XXX."); switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "User-Mask", "%s", "X."); switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Format", "%s", "wav"); switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Silence-Hits", "%d", 4); switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Silence-Threshold", "%d", 200); switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Maximum-Length", "%d", 30); if ((x_settings = switch_xml_child(x_profile, "settings"))) { switch_event_import_xml(switch_xml_child(x_settings, "param"), "name", "value", &profile->event_settings); } if ((x_apis = switch_xml_child(x_profile, "apis"))) { int total_options = 0; int total_invalid_options = 0; for (param = switch_xml_child(x_apis, "api"); param; param = param->next) { char *var, *val; if ((var = (char *) switch_xml_attr_soft(param, "name")) && (val = (char *) switch_xml_attr_soft(param, "value"))) { if (!strcasecmp(var, "msg_undelete") && !profile->api_msg_undelete) profile->api_msg_undelete = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "msg_delete") && !profile->api_msg_delete) profile->api_msg_delete = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "msg_list") && !profile->api_msg_list) profile->api_msg_list = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "msg_count") && !profile->api_msg_count) profile->api_msg_count = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "msg_save") && !profile->api_msg_save) profile->api_msg_save = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "msg_purge") && !profile->api_msg_purge) profile->api_msg_purge = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "msg_get") && !profile->api_msg_get) profile->api_msg_get = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "msg_forward") && !profile->api_msg_forward) profile->api_msg_forward = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "pref_greeting_set") && !profile->api_pref_greeting_set) profile->api_pref_greeting_set = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "pref_greeting_get") && !profile->api_pref_greeting_get) profile->api_pref_greeting_get = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "pref_recname_set") && !profile->api_pref_recname_set) profile->api_pref_recname_set = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "pref_password_set") && !profile->api_pref_password_set) profile->api_pref_password_set = switch_core_session_strdup(session, val); else if (!strcasecmp(var, "auth_login") && !profile->api_auth_login) profile->api_auth_login = switch_core_session_strdup(session, val); else total_invalid_options++; total_options++; } } if (total_options - total_invalid_options != 13) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing api definition for profile '%s'\n", profile_name); profile = NULL; } } } end: switch_xml_free(xml); return profile; }
/** * Start execution of call receivefax component * @param call the call to receive fax from * @param msg the original request * @param session_data the call's session */ static iks *start_receivefax_component(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { iks *iq = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; struct receivefax_component *receivefax_component = NULL; iks *receivefax = iks_find(iq, "receivefax"); iks *response = NULL; switch_event_t *execute_event = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_memory_pool_t *pool; int file_no; /* validate attributes */ if (!VALIDATE_RAYO_RECEIVEFAX(receivefax)) { return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST); } /* fax is only allowed if the call is not currently joined */ if (rayo_call_is_joined(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't receive fax on a joined call"); } if (rayo_call_is_faxing(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress"); } /* create receivefax component */ switch_core_new_memory_pool(&pool); receivefax_component = switch_core_alloc(pool, sizeof(*receivefax_component)); receivefax_component = RECEIVEFAX_COMPONENT(rayo_component_init((struct rayo_component *)receivefax_component, pool, RAT_CALL_COMPONENT, "receivefax", NULL, call, iks_find_attrib(iq, "from"))); if (!receivefax_component) { switch_core_destroy_memory_pool(&pool); return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "Failed to create sendfax entity"); } file_no = rayo_actor_seq_next(call); receivefax_component->filename = switch_core_sprintf(pool, "%s%s%s-%d.tif", globals.file_prefix, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); if (!strncmp(receivefax_component->filename, "http://", 7) || !strncmp(receivefax_component->filename, "https://", 8)) { /* This is an HTTP URL, need to PUT after fax is received */ receivefax_component->local_filename = switch_core_sprintf(pool, "%s%s%s-%d", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); receivefax_component->http_put_after_receive = 1; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to HTTP URL\n", RAYO_JID(receivefax_component)); } else { /* assume file.. */ receivefax_component->local_filename = receivefax_component->filename; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to local file\n", RAYO_JID(receivefax_component)); } /* add channel variable so that fax component can be located from fax events */ switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(receivefax_component)); /* clear fax result variables */ switch_channel_set_variable(channel, "fax_success", NULL); switch_channel_set_variable(channel, "fax_result_code", NULL); switch_channel_set_variable(channel, "fax_result_text", NULL); switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL); switch_channel_set_variable(channel, "fax_document_total_pages", NULL); switch_channel_set_variable(channel, "fax_image_resolution", NULL); switch_channel_set_variable(channel, "fax_image_size", NULL); switch_channel_set_variable(channel, "fax_bad_rows", NULL); switch_channel_set_variable(channel, "fax_transfer_rate", NULL); switch_channel_set_variable(channel, "fax_ecm_used", NULL); switch_channel_set_variable(channel, "fax_local_station_id", NULL); switch_channel_set_variable(channel, "fax_remote_station_id", NULL); rayo_call_set_faxing(RAYO_CALL(call), 1); /* execute rxfax APP */ if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "rxfax"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", receivefax_component->local_filename); if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); } if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to rxfax (queue event failed)"); if (execute_event) { switch_event_destroy(&execute_event); } rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_RELEASE(receivefax_component); } else { /* component starting... */ rayo_component_send_start(RAYO_COMPONENT(receivefax_component), iq); } } else { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create rxfax event"); rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_RELEASE(receivefax_component); } return response; }
void menu_init(vmivr_profile_t *profile, vmivr_menu_t *menu) { switch_xml_t cfg, xml, x_profiles, x_profile, x_keys, x_phrases, x_menus, x_menu, x_settings; menu->profile = profile; if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf); goto end; } if (!(x_profiles = switch_xml_child(cfg, "profiles"))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No profiles group\n"); goto end; } if (profile->event_settings) { /* TODO Replace this with a switch_event_merge_not_set(...) */ switch_event_t *menu_default; switch_event_create(&menu_default, SWITCH_EVENT_REQUEST_PARAMS); if (menu->event_settings) { switch_event_merge(menu_default, menu->event_settings); switch_event_destroy(&menu->event_settings); } switch_event_create(&menu->event_settings, SWITCH_EVENT_REQUEST_PARAMS); switch_event_merge(menu->event_settings, profile->event_settings); switch_event_merge(menu->event_settings, menu_default); switch_event_destroy(&menu_default); } { const char *s_max_attempts = switch_event_get_header(menu->event_settings, "IVR-Maximum-Attempts"); const char *s_entry_timeout = switch_event_get_header(menu->event_settings, "IVR-Entry-Timeout"); menu->ivr_maximum_attempts = atoi(s_max_attempts); menu->ivr_entry_timeout = atoi(s_entry_timeout); } if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile->name))) { if ((x_menus = switch_xml_child(x_profile, "menus"))) { if ((x_menu = switch_xml_find_child(x_menus, "menu", "name", menu->name))) { if ((x_keys = switch_xml_child(x_menu, "keys"))) { switch_event_import_xml(switch_xml_child(x_keys, "key"), "dtmf", "action", &menu->event_keys_dtmf); switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "dtmf", &menu->event_keys_action); switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "variable", &menu->event_keys_varname); } if ((x_phrases = switch_xml_child(x_menu, "phrases"))) { switch_event_import_xml(switch_xml_child(x_phrases, "phrase"), "name", "value", &menu->event_phrases); } if ((x_settings = switch_xml_child(x_menu, "settings"))) { switch_event_import_xml(switch_xml_child(x_settings, "param"), "name", "value", &menu->event_settings); } } } } if (!menu->phrase_params) { switch_event_create(&menu->phrase_params, SWITCH_EVENT_REQUEST_PARAMS); } end: if (xml) switch_xml_free(xml); return; }
static FIO_SIGNAL_CB_FUNCTION(on_signal_cb) { uint32_t chanid, spanid; switch_event_t *event = NULL; ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE; chanid = ftdm_channel_get_id(sigmsg->channel); spanid = ftdm_channel_get_span_id(sigmsg->channel); switch(sigmsg->event_id) { case FTDM_SIGEVENT_ALARM_CLEAR: case FTDM_SIGEVENT_ALARM_TRAP: { if (ftdm_channel_get_alarms(sigmsg->channel, &alarmbits) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "failed to retrieve alarms\n"); return FTDM_FAIL; } if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "failed to create alarms events\n"); return FTDM_FAIL; } if (sigmsg->event_id == FTDM_SIGEVENT_ALARM_CLEAR) { ftdm_log(FTDM_LOG_NOTICE, "Alarm cleared on channel %d:%d\n", spanid, chanid); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear"); } else { ftdm_log(FTDM_LOG_NOTICE, "Alarm raised on channel %d:%d\n", spanid, chanid); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap"); } } break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unhandled event %d\n", sigmsg->event_id); break; } if (event) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel)); if (alarmbits & FTDM_ALARM_RED) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red"); } if (alarmbits & FTDM_ALARM_YELLOW) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow"); } if (alarmbits & FTDM_ALARM_RAI) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai"); } if (alarmbits & FTDM_ALARM_BLUE) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue"); } if (alarmbits & FTDM_ALARM_AIS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais"); } if (alarmbits & FTDM_ALARM_GENERAL) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general"); } switch_event_fire(&event); } return FTDM_SUCCESS; }
SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *session) { switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state; const switch_endpoint_interface_t *endpoint_interface; const switch_state_handler_table_t *driver_state_handler = NULL; const switch_state_handler_table_t *application_state_handler = NULL; int proceed = 1; int global_proceed = 1; int do_extra_handlers = 1; int silly = 0; int index = 0; const char *var = switch_channel_get_variable(session->channel, SWITCH_PROCESS_CDR_VARIABLE); const char *hook_var; int use_session = 0; switch_event_t *event; switch_call_cause_t cause = switch_channel_get_cause(session->channel); if (switch_channel_test_flag(session->channel, CF_REPORTING)) { return; } switch_channel_set_flag(session->channel, CF_REPORTING); switch_assert(session != NULL); endpoint_interface = session->endpoint_interface; switch_assert(endpoint_interface != NULL); driver_state_handler = endpoint_interface->state_handler; switch_assert(driver_state_handler != NULL); if (!zstr(var)) { if (!strcasecmp(var, "a_only")) { if (switch_channel_get_originator_caller_profile(session->channel)) { do_extra_handlers = 0; } } else if (!strcasecmp(var, "b_only")) { if (switch_channel_get_originatee_caller_profile(session->channel)) { do_extra_handlers = 0; } } else if (!switch_true(var)) { do_extra_handlers = 0; } } STATE_MACRO(reporting, "REPORTING"); if ((hook_var = switch_channel_get_variable(session->channel, SWITCH_API_REPORTING_HOOK_VARIABLE))) { if (switch_true(switch_channel_get_variable(session->channel, SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE))) { use_session = 1; } api_hook(session, hook_var, use_session); } if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(cause)); switch_channel_event_set_data(session->channel, event); if (switch_true(switch_channel_get_variable(session->channel, "hangup_complete_with_xml"))) { switch_xml_t cdr = NULL; char *xml_cdr_text; if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) { xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CDR-Attached", "xml"); switch_event_add_body(event, "%s", xml_cdr_text); switch_xml_free(cdr); switch_safe_free(xml_cdr_text); } } switch_event_fire(&event); } return; }
static void parse_naptr(const ldns_rr *naptr, const char *number, enum_record_t **results) { char *str = ldns_rr2str(naptr); char *argv[11] = { 0 }; int i, argc; char *pack[4] = { 0 }; int packc; char *p; int order = 10; int preference = 100; char *service = NULL; char *packstr; char *regex, *replace; if (zstr(str)) { return; } for (p = str; p && *p; p++) { if (*p == '\t') *p = ' '; if (*p == ' ' && *(p+1) == '.') *p = '\0'; } argc = switch_split(str, ' ', argv); for (i = 0; i < argc; i++) { if (i > 0) { strip_quotes(argv[i]); } } service = argv[7]; packstr = argv[8]; if (zstr(service) || zstr(packstr)) { goto end; } if (!zstr(argv[4])) { order = atoi(argv[4]); } if (!zstr(argv[5])) { preference = atoi(argv[5]); } if ((packc = switch_split(packstr, '!', pack))) { regex = pack[1]; replace = pack[2]; } else { goto end; } for (p = replace; p && *p; p++) { if (*p == '\\') { *p = '$'; } } if (service && regex && replace) { switch_regex_t *re = NULL, *re2 = NULL; int proceed = 0, ovector[30]; char *substituted = NULL; char *substituted_2 = NULL; char *uri; char *uri_expanded = NULL; enum_route_t *route; int supported = 0; uint32_t len = 0; if ((proceed = switch_regex_perform(number, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { if (strchr(regex, '(')) { len = (uint32_t) (strlen(number) + strlen(replace) + 10) * proceed; if (!(substituted = malloc(len))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); switch_regex_safe_free(re); goto end; } memset(substituted, 0, len); switch_perform_substitution(re, proceed, replace, number, substituted, len, ovector); uri = substituted; } else { uri = replace; } switch_mutex_lock(MUTEX); for (route = globals.route_order; route; route = route->next) { if (strcasecmp(service, route->service)) { continue; } if ((proceed = switch_regex_perform(uri, route->regex, &re2, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_event_t *event = NULL; if (strchr(route->regex, '(')) { len = (uint32_t) (strlen(uri) + strlen(route->replace) + 10) * proceed; if (!(substituted_2 = malloc(len))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); switch_safe_free(substituted); switch_regex_safe_free(re); switch_regex_safe_free(re2); switch_mutex_unlock(MUTEX); goto end; } memset(substituted_2, 0, len); switch_perform_substitution(re2, proceed, route->replace, uri, substituted_2, len, ovector); uri = substituted_2; } else { uri = route->replace; } switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS); uri_expanded = switch_event_expand_headers(event, uri); switch_event_destroy(&event); if (uri_expanded == uri) { uri_expanded = NULL; } else { uri = uri_expanded; } supported++; add_result(results, order, preference, service, uri, supported); } switch_safe_free(uri_expanded); switch_safe_free(substituted_2); switch_regex_safe_free(re2); } switch_mutex_unlock(MUTEX); if (!supported) { add_result(results, order, preference, service, uri, 0); } switch_safe_free(substituted); switch_regex_safe_free(re); } } end: switch_safe_free(str); return; }
SWITCH_DECLARE(switch_status_t) switch_core_session_set_write_codec(switch_core_session_t *session, switch_codec_t *codec) { switch_event_t *event; switch_channel_t *channel = switch_core_session_get_channel(session); char tmp[30]; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_mutex_lock(session->codec_write_mutex); if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) { if (session->real_write_codec) { session->write_codec = session->real_write_codec; session->write_impl = *session->real_write_codec->implementation; session->real_write_codec = NULL; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n"); status = SWITCH_STATUS_FALSE; goto end; } } else if (session->write_codec) { if (session->real_write_codec) { if (codec == session->real_write_codec) { session->write_codec = codec; session->write_impl = *codec->implementation; session->real_write_codec = NULL; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot double-set codec!\n"); status = SWITCH_STATUS_FALSE; goto end; } } else { session->real_write_codec = session->write_codec; session->write_codec = codec; session->write_impl = *codec->implementation; } } else { session->write_codec = codec; session->write_impl = *codec->implementation; } if (session->write_codec && codec && session->write_impl.codec_id) { if (switch_event_create(&event, SWITCH_EVENT_CODEC) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", session->write_impl.iananame); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%d", session->write_impl.actual_samples_per_second); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-codec-bit-rate", "%d", session->write_impl.bits_per_second); if (session->write_impl.actual_samples_per_second != session->write_impl.samples_per_second) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Reported-Write-Codec-Rate", "%d", session->write_impl.actual_samples_per_second); } switch_event_fire(&event); } switch_channel_set_variable(channel, "write_codec", session->write_impl.iananame); switch_snprintf(tmp, sizeof(tmp), "%d", session->write_impl.actual_samples_per_second); switch_channel_set_variable(channel, "write_rate", tmp); } end: switch_mutex_unlock(session->codec_write_mutex); return status; }
static switch_status_t populate_database(switch_core_session_t *session, dir_profile_t *profile, const char *domain_name) { switch_status_t status = SWITCH_STATUS_SUCCESS; char *sql = NULL; char *sqlvalues = NULL; char *sqltmp = NULL; switch_xml_t xml_root = NULL, x_domain; switch_xml_t ut; switch_event_t *xml_params = NULL; switch_xml_t group = NULL, groups = NULL, users = NULL, x_params = NULL, x_param = NULL, x_vars = NULL, x_var = NULL; switch_event_create(&xml_params, SWITCH_EVENT_REQUEST_PARAMS); switch_assert(xml_params); if (switch_xml_locate_domain(domain_name, xml_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain_name); status = SWITCH_STATUS_FALSE; goto end; } if ((groups = switch_xml_child(x_domain, "groups"))) { for (group = switch_xml_child(groups, "group"); group; group = group->next) { if ((users = switch_xml_child(group, "users"))) { for (ut = switch_xml_child(users, "user"); ut; ut = ut->next) { int name_visible = 1; int exten_visible = 1; const char *type = switch_xml_attr_soft(ut, "type"); const char *id = switch_xml_attr_soft(ut, "id"); char *fullName = NULL; char *caller_name = NULL; char *caller_name_override = NULL; char *firstName = NULL; char *lastName = NULL; char *fullNameDigit = NULL; char *firstNameDigit = NULL; char *lastNameDigit = NULL; if (!strcasecmp(type, "pointer")) { continue; } /* Check all the user params */ if ((x_params = switch_xml_child(ut, "params"))) { for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) { const char *var = switch_xml_attr_soft(x_param, "name"); const char *val = switch_xml_attr_soft(x_param, "value"); if (!strcasecmp(var, "directory-visible")) { name_visible = switch_true(val); } if (!strcasecmp(var, "directory-exten-visible")) { exten_visible = switch_true(val); } } } /* Check all the user variables */ if ((x_vars = switch_xml_child(ut, "variables"))) { for (x_var = switch_xml_child(x_vars, "variable"); x_var; x_var = x_var->next) { const char *var = switch_xml_attr_soft(x_var, "name"); const char *val = switch_xml_attr_soft(x_var, "value"); if (!strcasecmp(var, "effective_caller_id_name")) { caller_name = switch_core_session_strdup(session, val); } if (!strcasecmp(var, "directory_full_name")) { caller_name_override = switch_core_session_strdup(session, val); } } } if (caller_name_override) { fullName = caller_name_override; } else { fullName = caller_name; } if (zstr(fullName)) { continue; } firstName = switch_core_session_strdup(session, fullName); if ((lastName = strrchr(firstName, ' '))) { *lastName++ = '\0'; } else { lastName = switch_core_session_strdup(session, firstName); } /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "FullName %s firstName [%s] lastName [%s]\n", fullName, firstName, lastName); */ /* Generate Digits key mapping */ fullNameDigit = string_to_keypad_digit(fullName); lastNameDigit = string_to_keypad_digit(lastName); firstNameDigit = string_to_keypad_digit(firstName); /* add user into DB */ sql = switch_mprintf("insert into directory_search values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%d','%d')", globals.hostname, switch_core_session_get_uuid(session), id, fullName, fullNameDigit, firstName, firstNameDigit, lastName, lastNameDigit, name_visible, exten_visible); if (sqlvalues) { sqltmp = sqlvalues; sqlvalues = switch_mprintf("%s;%s", sqlvalues, sql); switch_safe_free(sqltmp); } else { sqlvalues = sql; sql = NULL; } switch_safe_free(sql); switch_safe_free(fullNameDigit); switch_safe_free(lastNameDigit); switch_safe_free(firstNameDigit); } } } } sql = switch_mprintf("BEGIN;%s;COMMIT;", sqlvalues); directory_execute_sql(sql, globals.mutex); end: switch_safe_free(sql); switch_safe_free(sqlvalues); switch_event_destroy(&xml_params); switch_xml_free(xml_root); return status; }
SWITCH_DECLARE(switch_status_t) switch_core_session_set_read_codec(switch_core_session_t *session, switch_codec_t *codec) { switch_event_t *event; switch_channel_t *channel = switch_core_session_get_channel(session); char tmp[30]; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_mutex_lock(session->codec_read_mutex); if (codec && (!codec->implementation || !switch_core_codec_ready(codec))) { codec = NULL; } if (codec) { if (!session->real_read_codec) { session->read_codec = session->real_read_codec = codec; if (codec->implementation) { session->read_impl = *codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Push codec %s:%d\n", switch_channel_get_name(session->channel), codec->implementation->iananame, codec->implementation->ianacode); codec->next = session->read_codec; session->read_codec = codec; if (codec->implementation) { session->read_impl = *codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } } } else { if (session->read_codec == session->real_read_codec) { goto end; } if (session->read_codec->next) { switch_codec_t *old = session->read_codec; session->read_codec = session->read_codec->next; if (session->read_codec->implementation) { session->read_impl = *session->read_codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } old->next = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Restore previous codec %s:%d.\n", switch_channel_get_name(session->channel), session->read_impl.iananame ? session->read_impl.iananame : "N/A", session->read_impl.ianacode); } else if (session->real_read_codec) { session->read_codec = session->real_read_codec; if (session->real_read_codec->implementation) { session->read_impl = *session->real_read_codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Restore original codec.\n"); } else { status = SWITCH_STATUS_FALSE; goto end; } } if (!session->read_codec) { status = SWITCH_STATUS_FALSE; goto end; } if (session->read_codec && session->read_impl.decoded_bytes_per_packet) { if (switch_event_create(&event, SWITCH_EVENT_CODEC) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second); if (session->read_impl.actual_samples_per_second != session->read_impl.samples_per_second) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second); } switch_event_fire(&event); } switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame); switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second); switch_channel_set_variable(channel, "read_rate", tmp); session->raw_read_frame.codec = session->read_codec; session->raw_write_frame.codec = session->read_codec; session->enc_read_frame.codec = session->read_codec; session->enc_write_frame.codec = session->read_codec; } end: if (session->read_codec) { switch_channel_set_flag(channel, CF_MEDIA_SET); } switch_mutex_unlock(session->codec_read_mutex); return status; }
switch_status_t load_config() { CONFIG_VSAS* PCONFIGVSAS = NULL; CONFIG_CLIENT* PCONFIGCLIENT = NULL; char *cf = "rad_auth.conf"; switch_xml_t cfg, xml, settings, param; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_event_t *params = NULL; char *name; char *id; char *value; char *pec; char *expr; char* direction; CONFIGVSAS = NULL; CONFIGCLIENT = NULL; switch_event_create(¶ms, SWITCH_EVENT_MESSAGE); switch_assert(params); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile", "profile_rad_auth"); //vsas if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf); status = SWITCH_STATUS_FALSE; return status; } if ((settings = switch_xml_child(cfg, "settings"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { name = (char *) switch_xml_attr_soft(param, "name"); value = (char *) switch_xml_attr_soft(param, "value"); if (strcmp(name, "radius_config") == 0) { if (rc_config_file == NULL) rc_config_file = malloc(STR_LENGTH + 1); strcpy(rc_config_file, value); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "radius config: %s\n", value); } } } if ((settings = switch_xml_child(cfg, "vsas"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { if (CONFIGVSAS == NULL) { CONFIGVSAS = malloc(sizeof(CONFIG_VSAS)); PCONFIGVSAS = CONFIGVSAS; } else { PCONFIGVSAS->pNext = malloc(sizeof(CONFIG_VSAS)); PCONFIGVSAS = PCONFIGVSAS->pNext; } name = (char *) switch_xml_attr_soft(param, "name"); id = (char *) switch_xml_attr_soft(param, "id"); value = (char *) switch_xml_attr_soft(param, "value"); pec = (char *) switch_xml_attr_soft(param, "pec"); expr = (char *) switch_xml_attr_soft(param, "expr"); direction = (char *) switch_xml_attr_soft(param, "direction"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "config attr: %s, %s, %s, %s, %s, %s\n", name, id, value, pec, expr, direction); PCONFIGVSAS->name = (char*) malloc(STR_LENGTH + 1); PCONFIGVSAS->value = (char*) malloc(STR_LENGTH + 1); strncpy(PCONFIGVSAS->name, name, STR_LENGTH); strncpy(PCONFIGVSAS->value, value, STR_LENGTH); PCONFIGVSAS->id = atoi(id); PCONFIGVSAS->pec = atoi(pec); PCONFIGVSAS->expr = atoi(expr); if(strcmp(direction, "in") == 0) PCONFIGVSAS->direction = 1; else PCONFIGVSAS->direction = 0; PCONFIGVSAS->pNext = NULL; } } if ((settings = switch_xml_child(cfg, "client"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { if (CONFIGCLIENT == NULL) { CONFIGCLIENT = malloc(sizeof(CONFIG_CLIENT)); PCONFIGCLIENT = CONFIGCLIENT; } else { PCONFIGCLIENT->pNext = malloc(sizeof(CONFIG_CLIENT)); PCONFIGCLIENT = PCONFIGCLIENT->pNext; } name = (char *) switch_xml_attr_soft(param, "name"); value = (char *) switch_xml_attr_soft(param, "value"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "config client: %s, %s\n", name, value); PCONFIGCLIENT->name = (char*) malloc(STR_LENGTH + 1); PCONFIGCLIENT->value = (char*) malloc(STR_LENGTH + 1); strncpy(PCONFIGCLIENT->name, name, STR_LENGTH); strncpy(PCONFIGCLIENT->value, value, STR_LENGTH); PCONFIGCLIENT->pNext = NULL; } } switch_xml_free(xml); return status; }
static void *SWITCH_THREAD_FUNC switch_nat_multicast_runtime(switch_thread_t * thread, void *obj) { char *buf = NULL; char newip[16] = ""; char *pos; switch_event_t *event = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread started\n"); buf = (char *) malloc(MULTICAST_BUFFSIZE); switch_assert(buf); nat_globals_perm.running = 1; while (nat_globals_perm.running == 1) { size_t len = MULTICAST_BUFFSIZE; switch_status_t status; switch_bool_t do_repub = SWITCH_FALSE; memset(buf, 0, len); status = switch_socket_recvfrom(nat_globals_perm.maddress, nat_globals_perm.msocket, 0, buf, &len); if (!len) { if (SWITCH_STATUS_IS_BREAK(status)) { switch_yield(5000000); continue; } break; } if (nat_globals.nat_type == SWITCH_NAT_TYPE_UPNP) { /* look for our desc URL and servicetype in the packet */ if (strstr(buf, nat_globals.descURL) && (buf == NULL || strstr(buf, nat_globals.data.servicetype))) { if ((pos = strstr(buf, "NTS:"))) { pos = pos + 4; while (*pos && *pos == ' ') { pos++; } if (!strncmp(pos, "ssdp:alive", 10)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UPnP keep alive packet: \n%s\n", buf); /* did pub ip change */ newip[0] = '\0'; if (get_upnp_pubaddr(newip) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to get current pubaddr after receiving UPnP keep alive packet.\n"); } } else if (!strncmp(pos, "ssdp:byebye", 11)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "got UPnP signoff packet. Your NAT gateway is probably going offline.\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UPnP signoff packet: \n%s\n", buf); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got UNKNOWN UPnP keep alive packet: \n%s\n", buf); } } } } else { /* got some data in NAT-PMP mode, treat any data as a republish event */ if (get_pmp_pubaddr(newip) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to get current pubaddr after receiving UPnP keep alive packet.\n"); } } if ((strlen(newip) > 0) && strcmp(newip, "0.0.0.0") && strcmp(newip, nat_globals.pub_addr)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Public IP changed from '%s' to '%s'.\n", nat_globals.pub_addr, newip); do_repub = SWITCH_TRUE; switch_event_create(&event, SWITCH_EVENT_TRAP); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", nat_globals.pub_addr); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", newip); switch_event_fire(&event); switch_set_string(nat_globals.pub_addr, newip); switch_nat_reinit(); } if (do_repub) { switch_nat_republish(); } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NAT thread ending\n"); nat_globals_perm.running = 0; switch_safe_free(buf); return NULL; }
SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) { switch_channel_state_t state = CS_NEW, midstate = CS_DESTROY, endstate; const switch_endpoint_interface_t *endpoint_interface; const switch_state_handler_table_t *driver_state_handler = NULL; const switch_state_handler_table_t *application_state_handler = NULL; int silly = 0; uint32_t new_loops = 60000; /* Life of the channel. you have channel and pool in your session everywhere you go you use the session to malloc with switch_core_session_alloc(session, <size>) The endpoint module gets the first crack at implementing the state if it wants to, it can cancel the default behavior by returning SWITCH_STATUS_FALSE Next comes the channel's event handler table that can be set by an application which also can veto the next behavior in line by returning SWITCH_STATUS_FALSE Finally the default state behavior is called. */ switch_assert(session != NULL); switch_set_flag(session, SSF_THREAD_RUNNING); endpoint_interface = session->endpoint_interface; switch_assert(endpoint_interface != NULL); driver_state_handler = endpoint_interface->state_handler; switch_assert(driver_state_handler != NULL); switch_mutex_lock(session->mutex); while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) { if (switch_channel_test_flag(session->channel, CF_BLOCK_STATE)) { switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL); if ((state = switch_channel_get_state(session->channel)) == CS_DESTROY) { break; } } midstate = state; if (state != switch_channel_get_running_state(session->channel) || state >= CS_HANGUP) { int index = 0; int proceed = 1; int global_proceed = 1; int do_extra_handlers = 1; switch_io_event_hook_state_run_t *ptr; switch_status_t rstatus = SWITCH_STATUS_SUCCESS; switch_channel_set_running_state(session->channel, state); switch_channel_clear_flag(session->channel, CF_TRANSFER); switch_channel_clear_flag(session->channel, CF_REDIRECT); if (session->endpoint_interface->io_routines->state_run) { rstatus = session->endpoint_interface->io_routines->state_run(session); } if (rstatus == SWITCH_STATUS_SUCCESS) { for (ptr = session->event_hooks.state_run; ptr; ptr = ptr->next) { if ((rstatus = ptr->state_run(session)) != SWITCH_STATUS_SUCCESS) { break; } } } switch (state) { case CS_NEW: /* Just created, Waiting for first instructions */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel)); break; case CS_DESTROY: goto done; case CS_REPORTING: /* Call Detail */ { switch_core_session_reporting_state(session); switch_channel_set_state(session->channel, CS_DESTROY); } goto done; case CS_HANGUP: /* Deactivate and end the thread */ { switch_core_session_hangup_state(session, SWITCH_TRUE); switch_channel_set_state(session->channel, CS_REPORTING); } break; case CS_INIT: /* Basic setup tasks */ { switch_event_t *event; STATE_MACRO(init, "INIT"); if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CREATE) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } } break; case CS_ROUTING: /* Look for a dialplan and find something to do */ STATE_MACRO(routing, "ROUTING"); break; case CS_RESET: /* Reset */ STATE_MACRO(reset, "RESET"); break; /* These other states are intended for prolonged durations so we do not signal lock for them */ case CS_EXECUTE: /* Execute an Operation */ STATE_MACRO(execute, "EXECUTE"); break; case CS_EXCHANGE_MEDIA: /* loop all data back to source */ STATE_MACRO(exchange_media, "EXCHANGE_MEDIA"); break; case CS_SOFT_EXECUTE: /* send/recieve data to/from another channel */ STATE_MACRO(soft_execute, "SOFT_EXECUTE"); break; case CS_PARK: /* wait in limbo */ STATE_MACRO(park, "PARK"); break; case CS_CONSUME_MEDIA: /* wait in limbo */ STATE_MACRO(consume_media, "CONSUME_MEDIA"); break; case CS_HIBERNATE: /* sleep */ STATE_MACRO(hibernate, "HIBERNATE"); break; case CS_NONE: abort(); break; } if (midstate == CS_DESTROY) { break; } } endstate = switch_channel_get_state(session->channel); if (endstate == switch_channel_get_running_state(session->channel)) { if (endstate == CS_NEW) { switch_cond_next(); switch_ivr_parse_all_events(session); if (!--new_loops) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s Timeout waiting for next instruction in CS_NEW!\n", session->uuid_str); switch_channel_hangup(session->channel, SWITCH_CAUSE_INVALID_CALL_REFERENCE); } } else { switch_ivr_parse_all_events(session); switch_ivr_parse_all_events(session); if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING); if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { switch_thread_cond_wait(session->cond, session->mutex); } switch_channel_clear_flag(session->channel, CF_THREAD_SLEEPING); } switch_ivr_parse_all_events(session); switch_ivr_parse_all_events(session); } } } done: switch_mutex_unlock(session->mutex); switch_clear_flag(session, SSF_THREAD_RUNNING); }
static void pres_event_handler(switch_event_t *event) { char *to = switch_event_get_header(event, "to"); char *dup_to = NULL, *lot_name, *dup_lot_name = NULL, *domain_name; valet_lot_t *lot; int found = 0; if (!to || strncasecmp(to, "park+", 5) || !strchr(to, '@')) { return; } if (!(dup_to = strdup(to))) { return; } lot_name = dup_to + 5; if ((domain_name = strchr(lot_name, '@'))) { *domain_name++ = '\0'; } dup_lot_name = switch_mprintf("%q@%q", lot_name, domain_name); if ((lot = valet_find_lot(lot_name, SWITCH_FALSE)) || (dup_lot_name && (lot = valet_find_lot(dup_lot_name, SWITCH_FALSE)))) { int count = valet_lot_count(lot); if (count) { if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d caller%s)", count, count == 1 ? "" : "s"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "active"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "confirmed"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound"); switch_event_fire(&event); } found++; } } else { if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Empty"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound"); switch_event_fire(&event); } } } else { switch_console_callback_match_t *matches = NULL; switch_console_callback_match_node_t *m; switch_hash_index_t *hi; const void *var; void *val; const char *nvar; switch_mutex_lock(globals.mutex); for (hi = switch_hash_first(NULL, globals.hash); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, &var, NULL, &val); nvar = (const char *) var; if (!strchr(nvar, '@') || switch_stristr(domain_name, nvar)) { switch_console_push_match(&matches, nvar); } } switch_mutex_unlock(globals.mutex); if (matches) { valet_token_t *token; for (m = matches->head; !found && m; m = m->next) { lot = valet_find_lot(m->val, SWITCH_FALSE); switch_mutex_lock(lot->mutex); if ((token = (valet_token_t *) switch_core_hash_find(lot->hash, lot_name)) && !token->timeout) { found++; if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", token->bridged == 0 ? "Holding" : "Active"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", token->bridged == 0 ? "early" : "confirmed"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", token->bridged == 0 ? "outbound" : "inbound"); switch_event_fire(&event); } } switch_mutex_unlock(lot->mutex); } switch_console_free_matches(&matches); } } if (!found && switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Empty"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound"); switch_event_fire(&event); } switch_safe_free(dup_to); switch_safe_free(dup_lot_name); }