static switch_bool_t amd_handle_voiced_frame(amd_vad_t *vad, const switch_frame_t *f) { vad->voice_duration += vad->frame_ms; if (vad->voice_duration >= globals.minimum_word_length && vad->state == VAD_STATE_IN_SILENCE) { vad->words++; switch_log_printf( SWITCH_CHANNEL_SESSION_LOG(vad->session), SWITCH_LOG_DEBUG, "AMD: Word detected (words: %d)\n", vad->words); vad->state = VAD_STATE_IN_WORD; } if (vad->voice_duration >= globals.maximum_word_length) { switch_log_printf( SWITCH_CHANNEL_SESSION_LOG(vad->session), SWITCH_LOG_DEBUG, "AMD: MACHINE (voice_duration: %d, maximum_word_length: %d)\n", vad->voice_duration, globals.maximum_word_length); switch_channel_set_variable(vad->channel, "amd_result", "MACHINE"); switch_channel_set_variable(vad->channel, "amd_cause", "MAXWORDLENGTH"); return SWITCH_TRUE; } if (vad->words >= globals.maximum_number_of_words) { switch_log_printf( SWITCH_CHANNEL_SESSION_LOG(vad->session), SWITCH_LOG_DEBUG, "AMD: MACHINE (words: %d, maximum_number_of_words: %d)\n", vad->words, globals.maximum_number_of_words); switch_channel_set_variable(vad->channel, "amd_result", "MACHINE"); switch_channel_set_variable(vad->channel, "amd_cause", "MAXWORDS"); return SWITCH_TRUE; } if (vad->in_greeting && vad->voice_duration >= globals.greeting) { switch_log_printf( SWITCH_CHANNEL_SESSION_LOG(vad->session), SWITCH_LOG_DEBUG, "AMD: MACHINE (voice_duration: %d, greeting: %d)\n", vad->voice_duration, globals.greeting); switch_channel_set_variable(vad->channel, "amd_result", "MACHINE"); switch_channel_set_variable(vad->channel, "amd_cause", "LONGGREETING"); return SWITCH_TRUE; } if (vad->voice_duration >= globals.minimum_word_length) { if (vad->silence_duration) { switch_log_printf( SWITCH_CHANNEL_SESSION_LOG(vad->session), SWITCH_LOG_DEBUG, "AMD: Detected Talk, previous silence duration: %dms\n", vad->silence_duration); } vad->silence_duration = 0; } if (vad->voice_duration >= globals.minimum_word_length && !vad->in_greeting) { if (vad->silence_duration) { switch_log_printf( SWITCH_CHANNEL_SESSION_LOG(vad->session), SWITCH_LOG_DEBUG, "AMD: Before Greeting Time (silence_duration: %d, voice_duration: %d)\n", vad->silence_duration, vad->voice_duration); } vad->in_initial_silence = 0; vad->in_greeting = 1; } return SWITCH_FALSE; }
/*! \brief Find voicemail beep in the audio stream * * @author Eric des Courtis * @param vmd_info The session information associated with the call. * @param frame The audio data. * @return The success or failure of the function. */ static void find_beep(vmd_session_info_t *vmd_info, switch_frame_t *frame) { int i; int c; double m[POINTS]; double med; unsigned int j = (vmd_info->pos + 1) % POINTS; unsigned int k = j; switch_event_t *event; switch_status_t status; switch_event_t *event_copy; switch_channel_t *channel = switch_core_session_get_channel(vmd_info->session); switch (vmd_info->state) { case BEEP_DETECTED: for (c = 0, i = 0; i < POINTS; j++, j %= POINTS, i++) { vmd_info->timestamp++; if (vmd_info->points[j].freq < TOLERANCE_T(vmd_info->beep_freq) && vmd_info->points[j].freq > TOLERANCE_B(vmd_info->beep_freq)) { c++; vmd_info->beep_freq = (vmd_info->beep_freq * 0.95) + (vmd_info->points[j].freq * 0.05); } } if (c < (POINTS - MAX_CHIRP)) { vmd_info->state = BEEP_NOT_DETECTED; if (vmd_info->timestamp < (switch_size_t) vmd_info->minTime) { break; } status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VMD_EVENT_BEEP); if (status != SWITCH_STATUS_SUCCESS) { return; } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Beep-Status", "stop"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Beep-Time", "%d", (int) vmd_info->timestamp / POINTS); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(vmd_info->session)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Frequency", "%6.4lf", vmd_info->beep_freq); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "vmd"); if ((switch_event_dup(&event_copy, event)) != SWITCH_STATUS_SUCCESS) { return; } switch_core_session_queue_event(vmd_info->session, &event); switch_event_fire(&event_copy); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(vmd_info->session), SWITCH_LOG_INFO, "<<< VMD - Beep Detected >>>\n"); switch_channel_set_variable(channel, "vmd_detect", "TRUE"); vmd_info->timestamp = 0; } break; case BEEP_NOT_DETECTED: for (i = 0; i < POINTS; k++, k %= POINTS, i++) { m[i] = vmd_info->points[k].freq; if (ISNAN(m[i])) { m[i] = 0.0; } } med = median(m, POINTS); if (ISNAN(med)) { for (i = 0; i < POINTS; i++) { if (!ISNAN(m[i])) { med = m[i]; break; } } } for (c = 0, i = 0; i < POINTS; j++, j %= POINTS, i++) { if (vmd_info->points[j].freq < TOLERANCE_T(med) && vmd_info->points[j].freq > TOLERANCE_B(med)) { if (vmd_info->points[j].ampl > MIN_AMPL && vmd_info->points[j].freq > MIN_FREQ && vmd_info->points[j].freq < MAX_FREQ) { c++; } } } if (c >= VALID) { vmd_info->state = BEEP_DETECTED; vmd_info->beep_freq = med; vmd_info->timestamp = 0; } break; } }
static switch_status_t shout_file_set_string(switch_file_handle_t *handle, switch_audio_col_t col, const char *string) { shout_context_t *context = handle->private_info; switch_status_t status = SWITCH_STATUS_FALSE; if (!context->shout) { switch (col) { case SWITCH_AUDIO_COL_STR_TITLE: id3tag_set_title(context->gfp, string); break; case SWITCH_AUDIO_COL_STR_COMMENT: id3tag_set_comment(context->gfp, string); break; case SWITCH_AUDIO_COL_STR_ARTIST: id3tag_set_artist(context->gfp, string); break; case SWITCH_AUDIO_COL_STR_DATE: id3tag_set_year(context->gfp, string); break; case SWITCH_AUDIO_COL_STR_SOFTWARE: break; id3tag_set_album(context->gfp, string); case SWITCH_AUDIO_COL_STR_COPYRIGHT: id3tag_set_genre(context->gfp, string); break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Value Ignored %d, %s\n", col, string); break; } return status; } switch (col) { case SWITCH_AUDIO_COL_STR_TITLE: if (shout_set_name(context->shout, string) == SHOUTERR_SUCCESS) { status = SWITCH_STATUS_SUCCESS; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout)); } break; case SWITCH_AUDIO_COL_STR_COMMENT: if (shout_set_url(context->shout, string) == SHOUTERR_SUCCESS) { status = SWITCH_STATUS_SUCCESS; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout)); } break; case SWITCH_AUDIO_COL_STR_ARTIST: if (shout_set_description(context->shout, string) == SHOUTERR_SUCCESS) { status = SWITCH_STATUS_SUCCESS; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout)); } break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Value Ignored %d, %s\n", col, string); break; } 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_status_t mod_amqp_command_create(char *name, switch_xml_t cfg) { mod_amqp_command_profile_t *profile = NULL; switch_xml_t params, param, connections, connection; switch_threadattr_t *thd_attr = NULL; switch_memory_pool_t *pool; char *exchange = NULL, *binding_key = NULL, *queue = NULL; if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { goto err; } profile = switch_core_alloc(pool, sizeof(mod_amqp_command_profile_t)); profile->pool = pool; profile->name = switch_core_strdup(profile->pool, name); profile->running = 1; profile->reconnect_interval_ms = 1000; if ((params = switch_xml_child(cfg, "params")) != NULL) { for (param = switch_xml_child(params, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); if (!var) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param missing 'name' attribute\n", profile->name); continue; } if (!val) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param[%s] missing 'value' attribute\n", profile->name, var); continue; } if (!strncmp(var, "reconnect_interval_ms", 21)) { int interval = atoi(val); if ( interval && interval > 0 ) { profile->reconnect_interval_ms = interval; } } else if (!strncmp(var, "exchange-name", 13)) { exchange = switch_core_strdup(profile->pool, val); } else if (!strncmp(var, "queue-name", 10)) { queue = switch_core_strdup(profile->pool, val); } else if (!strncmp(var, "binding_key", 11)) { binding_key = switch_core_strdup(profile->pool, val); } } } /* Handle defaults of string types */ profile->exchange = exchange ? exchange : switch_core_strdup(profile->pool, "TAP.Commands"); profile->queue = queue ? queue : NULL; profile->binding_key = binding_key ? binding_key : switch_core_strdup(profile->pool, "commandBindingKey"); if ((connections = switch_xml_child(cfg, "connections")) != NULL) { for (connection = switch_xml_child(connections, "connection"); connection; connection = connection->next) { if ( ! profile->conn_root ) { /* Handle first root node */ if (mod_amqp_connection_create(&(profile->conn_root), connection, profile->pool) != SWITCH_STATUS_SUCCESS) { /* Handle connection create failure */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Profile[%s] failed to create connection\n", profile->name); continue; } profile->conn_active = profile->conn_root; } else { if (mod_amqp_connection_create(&(profile->conn_active->next), connection, profile->pool) != SWITCH_STATUS_SUCCESS) { /* Handle connection create failure */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Profile[%s] failed to create connection\n", profile->name); continue; } profile->conn_active = profile->conn_active->next; } } } profile->conn_active = NULL; /* We are not going to open the command queue connection on create, but instead wait for the running thread to open it */ /* Start the worker threads */ switch_threadattr_create(&thd_attr, profile->pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); if (switch_thread_create(&profile->command_thread, thd_attr, mod_amqp_command_thread, profile, profile->pool)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create 'amqp event sender' thread!\n"); goto err; } if ( switch_core_hash_insert(globals.command_hash, name, (void *) profile) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to insert new profile [%s] into mod_amqp profile hash\n", name); goto err; } return SWITCH_STATUS_SUCCESS; err: /* Cleanup */ mod_amqp_command_destroy(&profile); return SWITCH_STATUS_GENERR; }
/** * Wraps file with interface that can be controlled by fileman flags * @param handle * @param path the file to play * @return SWITCH_STATUS_SUCCESS if opened */ static switch_status_t fileman_file_open(switch_file_handle_t *handle, const char *path) { switch_status_t status = SWITCH_STATUS_FALSE; struct fileman_file_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context)); handle->private_info = context; if (handle->params) { const char *id = switch_event_get_header(handle->params, "id"); const char *uuid = switch_event_get_header(handle->params, "session"); if (!zstr(id)) { context->id = switch_core_strdup(handle->memory_pool, id); } if (!zstr(uuid)) { context->uuid = switch_core_strdup(handle->memory_pool, uuid); } } switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Got path %s\n", path); if ((status = switch_core_file_open(&context->fh, path, handle->channels, handle->samplerate, handle->flags, NULL)) != SWITCH_STATUS_SUCCESS) { return status; } /* set up handle for external control */ if (!context->id) { /* use filename as ID */ context->id = switch_core_strdup(handle->memory_pool, path); } switch_mutex_lock(fileman_globals.mutex); if (!switch_core_hash_find(fileman_globals.hash, context->id)) { switch_core_hash_insert(fileman_globals.hash, context->id, handle); } else { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "Duplicate fileman ID: %s\n", context->id); return SWITCH_STATUS_FALSE; } switch_mutex_unlock(fileman_globals.mutex); context->max_frame_len = (handle->samplerate / 1000 * SWITCH_MAX_INTERVAL); switch_zmalloc(context->abuf, FILE_STARTBYTES * sizeof(*context->abuf)); if (!context->fh.audio_buffer) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Create audio buffer\n"); switch_buffer_create_dynamic(&context->fh.audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0); switch_assert(context->fh.audio_buffer); } handle->samples = context->fh.samples; handle->format = context->fh.format; handle->sections = context->fh.sections; handle->seekable = context->fh.seekable; handle->speed = context->fh.speed; handle->vol = context->fh.vol; handle->offset_pos = context->fh.offset_pos; handle->interval = context->fh.interval; if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) { switch_set_flag(handle, SWITCH_FILE_NATIVE); } else { switch_clear_flag(handle, SWITCH_FILE_NATIVE); } if (handle->params && switch_true(switch_event_get_header(handle->params, "pause"))) { switch_set_flag(handle, SWITCH_FILE_PAUSE); } return status; }
cc_status_t cc_agent_update(const char *key, const char *value, const char *agent) { cc_status_t result = CC_STATUS_SUCCESS; char *sql; char res[256]; switch_event_t *event; /* Check to see if agent already exist */ sql = switch_mprintf("SELECT count(*) FROM agents WHERE name = '%q'", agent); cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res)); switch_safe_free(sql); if (atoi(res) == 0) { result = CC_STATUS_AGENT_NOT_FOUND; goto done; } if (!strcasecmp(key, "status")) { if (cc_agent_str2status(value) != CC_AGENT_STATUS_UNKNOWN) { /* Reset values on available only */ if (cc_agent_str2status(value) == CC_AGENT_STATUS_AVAILABLE) { sql = switch_mprintf("UPDATE agents SET status = '%q', last_status_change = '%" SWITCH_TIME_T_FMT "', talk_time = 0, calls_answered = 0, no_answer_count = 0" " WHERE name = '%q' AND NOT status = '%q'", value, local_epoch_time_now(NULL), agent, value); } else { sql = switch_mprintf("UPDATE agents SET status = '%q', last_status_change = '%" SWITCH_TIME_T_FMT "' WHERE name = '%q'", value, local_epoch_time_now(NULL), agent); } cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); /* Used to stop any active callback */ if (cc_agent_str2status(value) != CC_AGENT_STATUS_AVAILABLE) { sql = switch_mprintf("SELECT uuid FROM members WHERE serving_agent = '%q' AND serving_system = 'single_box' AND NOT state = 'Answered'", agent); cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res)); switch_safe_free(sql); if (!switch_strlen_zero(res)) { // switch_core_session_hupall_matching_var("cc_member_pre_answer_uuid", res, SWITCH_CAUSE_ORIGINATOR_CANCEL); /*hmeng*/ switch_core_session_hupall_matching_var_ans("cc_member_pre_answer_uuid", res, SWITCH_CAUSE_ORIGINATOR_CANCEL, (switch_hup_type_t) (SHT_UNANSWERED | SHT_ANSWERED)); } } // get operator sql = switch_mprintf("SELECT name FROM operators WHERE agent = '%q'", agent); cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res)); switch_safe_free(sql); result = CC_STATUS_SUCCESS; if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Operator", res); // res --> operator.name switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-change"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", value); switch_event_fire(&event); } } else { result = CC_STATUS_AGENT_INVALID_STATUS; goto done; } } else if (!strcasecmp(key, "state")) { if (cc_agent_str2state(value) != CC_AGENT_STATE_UNKNOWN) { if (cc_agent_str2state(value) != CC_AGENT_STATE_RECEIVING) { sql = switch_mprintf("UPDATE agents SET state = '%q' WHERE name = '%q'", value, agent); } else { sql = switch_mprintf("UPDATE agents SET state = '%q', last_offered_call = '%" SWITCH_TIME_T_FMT "' WHERE name = '%q'", value, local_epoch_time_now(NULL), agent); } cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-state-change"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-State", value); switch_event_fire(&event); } } else { result = CC_STATUS_AGENT_INVALID_STATE; goto done; } } else if (!strcasecmp(key, "uuid")) { sql = switch_mprintf("UPDATE agents SET uuid = '%q', system = 'single_box' WHERE name = '%q'", value, agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "contact")) { sql = switch_mprintf("UPDATE agents SET contact = '%q', system = 'single_box' WHERE name = '%q'", value, agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "ready_time")) { sql = switch_mprintf("UPDATE agents SET ready_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "busy_delay_time")) { sql = switch_mprintf("UPDATE agents SET busy_delay_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "reject_delay_time")) { sql = switch_mprintf("UPDATE agents SET reject_delay_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "no_answer_delay_time")) { sql = switch_mprintf("UPDATE agents SET no_answer_delay_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "type")) { if (strcasecmp(value, CC_AGENT_TYPE_CALLBACK) && strcasecmp(value, CC_AGENT_TYPE_UUID_STANDBY)) { result = CC_STATUS_AGENT_INVALID_TYPE; goto done; } sql = switch_mprintf("UPDATE agents SET type = '%q' WHERE name = '%q'", value, agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "max_no_answer")) { sql = switch_mprintf("UPDATE agents SET max_no_answer = '%d', system = 'single_box' WHERE name = '%q'", atoi(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "wrap_up_time")) { sql = switch_mprintf("UPDATE agents SET wrap_up_time = '%d', system = 'single_box' WHERE name = '%q'", atoi(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else { result = CC_STATUS_INVALID_KEY; goto done; } done: if (result == CC_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Updated Agent %s set %s = %s\n", agent, key, value); } return result; }
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_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; } } *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"; switch_core_session_get_read_impl(session, &bug->read_impl); switch_core_session_get_write_impl(session, &bug->write_impl); 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 = bug->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 = bug->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 switch_status_t my_on_reporting(switch_core_session_t *session) { switch_xml_t cdr = NULL; char *xml_text = NULL; char *path = NULL; char *curl_xml_text = NULL; const char *logdir = NULL; char *xml_text_escaped = NULL; int fd = -1; uint32_t cur_try; long httpRes; CURL *curl_handle = NULL; struct curl_slist *headers = NULL; struct curl_slist *slist = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_FALSE; int is_b; const char *a_prefix = ""; if (globals.shutdown) { return SWITCH_STATUS_SUCCESS; } is_b = channel && switch_channel_get_originator_caller_profile(channel); if (!globals.log_b && is_b) { const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE); if (!switch_true(force_cdr)) { return SWITCH_STATUS_SUCCESS; } } if (!is_b && globals.prefix_a) a_prefix = "a_"; if (switch_ivr_generate_xml_cdr(session, &cdr) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Generating Data!\n"); return SWITCH_STATUS_FALSE; } /* build the XML */ xml_text = switch_xml_toxml(cdr, SWITCH_TRUE); if (!xml_text) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); goto error; } switch_thread_rwlock_rdlock(globals.log_path_lock); if (!(logdir = switch_channel_get_variable(channel, "xml_cdr_base"))) { logdir = globals.log_dir; } if (!zstr(logdir) && (globals.log_http_and_disk || !globals.url_count)) { path = switch_mprintf("%s%s%s%s.cdr.xml", logdir, SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session)); switch_thread_rwlock_unlock(globals.log_path_lock); if (path) { #ifdef _MSC_VER if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) { #else if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) { #endif int wrote; wrote = write(fd, xml_text, (unsigned) strlen(xml_text)); wrote++; close(fd); fd = -1; } else { char ebuf[512] = { 0 }; #ifdef WIN32 strerror_s(ebuf, sizeof(ebuf), errno); #else strerror_r(errno, ebuf, sizeof(ebuf)); #endif switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s][%s]\n", path, ebuf); } switch_safe_free(path); } } else { switch_thread_rwlock_unlock(globals.log_path_lock); } /* try to post it to the web server */ if (globals.url_count) { char *destUrl = NULL; curl_handle = curl_easy_init(); if (globals.encode == ENCODING_TEXTXML) { headers = curl_slist_append(headers, "Content-Type: text/xml"); } else if (globals.encode) { switch_size_t need_bytes = strlen(xml_text) * 3 + 1; xml_text_escaped = malloc(need_bytes); switch_assert(xml_text_escaped); memset(xml_text_escaped, 0, need_bytes); if (globals.encode == ENCODING_DEFAULT) { headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); switch_url_encode(xml_text, xml_text_escaped, need_bytes); } else { headers = curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded"); switch_b64_encode((unsigned char *) xml_text, need_bytes / 3, (unsigned char *) xml_text_escaped, need_bytes); } switch_safe_free(xml_text); xml_text = xml_text_escaped; } else { headers = curl_slist_append(headers, "Content-Type: application/x-www-form-plaintext"); } if (globals.encode == ENCODING_TEXTXML) { curl_xml_text = xml_text; } else if (!(curl_xml_text = switch_mprintf("cdr=%s", xml_text))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); goto error; } if (!zstr(globals.cred)) { curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, globals.auth_scheme); curl_easy_setopt(curl_handle, CURLOPT_USERPWD, globals.cred); } curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl_handle, CURLOPT_POST, 1); curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, curl_xml_text); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-xml/1.0"); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, httpCallBack); if (globals.disable100continue) { slist = curl_slist_append(slist, "Expect:"); curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist); } if (globals.ssl_cert_file) { curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, globals.ssl_cert_file); } if (globals.ssl_key_file) { curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, globals.ssl_key_file); } if (globals.ssl_key_password) { curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, globals.ssl_key_password); } if (globals.ssl_version) { if (!strcasecmp(globals.ssl_version, "SSLv3")) { curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3); } else if (!strcasecmp(globals.ssl_version, "TLSv1")) { curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); } } if (globals.ssl_cacert_file) { curl_easy_setopt(curl_handle, CURLOPT_CAINFO, globals.ssl_cacert_file); } curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals.timeout); /* these were used for testing, optionally they may be enabled if someone desires curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level */ for (cur_try = 0; cur_try < globals.retries; cur_try++) { if (cur_try > 0) { switch_yield(globals.delay * 1000000); } destUrl = switch_mprintf("%s?uuid=%s%s", globals.urls[globals.url_index], a_prefix, switch_core_session_get_uuid(session)); curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl); if (!strncasecmp(destUrl, "https", 5)) { curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); } if (globals.enable_cacert_check) { curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE); } if (globals.enable_ssl_verifyhost) { curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2); } curl_easy_perform(curl_handle); curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes); switch_safe_free(destUrl); if (httpRes == 200) { goto success; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Got error [%ld] posting to web server [%s]\n", httpRes, globals.urls[globals.url_index]); globals.url_index++; switch_assert(globals.url_count <= MAX_URLS); if (globals.url_index >= globals.url_count) { globals.url_index = 0; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retry will be with url [%s]\n", globals.urls[globals.url_index]); } } curl_easy_cleanup(curl_handle); curl_slist_free_all(headers); curl_slist_free_all(slist); slist = NULL; headers = NULL; curl_handle = NULL; /* if we are here the web post failed for some reason */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to post to web server, writing to file\n"); switch_thread_rwlock_rdlock(globals.log_path_lock); path = switch_mprintf("%s%s%s%s.cdr.xml", globals.err_log_dir, SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session)); switch_thread_rwlock_unlock(globals.log_path_lock); if (path) { #ifdef _MSC_VER if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) { #else if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) { #endif int wrote; wrote = write(fd, xml_text, (unsigned) strlen(xml_text)); wrote++; close(fd); fd = -1; } else { char ebuf[512] = { 0 }; #ifdef WIN32 strerror_s(ebuf, sizeof(ebuf), errno); #else strerror_r(errno, ebuf, sizeof(ebuf)); #endif switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error![%s]\n", ebuf); } } } success: status = SWITCH_STATUS_SUCCESS; error: if (curl_handle) { curl_easy_cleanup(curl_handle); } if (headers) { curl_slist_free_all(headers); } if (slist) { curl_slist_free_all(slist); } if (curl_xml_text != xml_text) { switch_safe_free(curl_xml_text); } switch_safe_free(xml_text); switch_safe_free(path); switch_xml_free(cdr); return status; } static void event_handler(switch_event_t *event) { const char *sig = switch_event_get_header(event, "Trapped-Signal"); if (sig && !strcmp(sig, "HUP")) { if (globals.rotate) { set_xml_cdr_log_dirs(); } } } static switch_state_handler_table_t state_handlers = { /*.on_init */ NULL, /*.on_routing */ NULL, /*.on_execute */ NULL, /*.on_hangup */ NULL, /*.on_exchange_media */ NULL, /*.on_soft_execute */ NULL, /*.on_consume_media */ NULL, /*.on_hibernate */ NULL, /*.on_reset */ NULL, /*.on_park */ NULL, /*.on_reporting */ my_on_reporting }; SWITCH_MODULE_LOAD_FUNCTION(mod_xml_cdr_load) { char *cf = "xml_cdr.conf"; switch_xml_t cfg, xml, settings, param; switch_status_t status = SWITCH_STATUS_SUCCESS; /* test global state handlers */ switch_core_add_state_handler(&state_handlers); *module_interface = switch_loadable_module_create_module_interface(pool, modname); memset(&globals, 0, sizeof(globals)); if (switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } globals.log_http_and_disk = 0; globals.log_b = 1; globals.disable100continue = 0; globals.pool = pool; globals.auth_scheme = CURLAUTH_BASIC; switch_thread_rwlock_create(&globals.log_path_lock, pool); /* parse the config */ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); return SWITCH_STATUS_TERM; } if ((settings = switch_xml_child(cfg, "settings"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "cred") && !zstr(val)) { globals.cred = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "url") && !zstr(val)) { if (globals.url_count >= MAX_URLS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "maximum urls configured!\n"); } else { globals.urls[globals.url_count++] = switch_core_strdup(globals.pool, val); } } else if (!strcasecmp(var, "log-http-and-disk")) { globals.log_http_and_disk = switch_true(val); } else if (!strcasecmp(var, "timeout")) { int tmp = atoi(val); if (tmp >= 0) { globals.timeout = tmp; } else { globals.timeout = 0; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set a negative timeout!\n"); } } else if (!strcasecmp(var, "delay") && !zstr(val)) { globals.delay = (uint32_t) atoi(val); } else if (!strcasecmp(var, "log-b-leg")) { globals.log_b = switch_true(val); } else if (!strcasecmp(var, "prefix-a-leg")) { globals.prefix_a = switch_true(val); } else if (!strcasecmp(var, "disable-100-continue") && switch_true(val)) { globals.disable100continue = 1; } else if (!strcasecmp(var, "encode") && !zstr(val)) { if (!strcasecmp(val, "base64")) { globals.encode = ENCODING_BASE64; } else if (!strcasecmp(val, "textxml")) { globals.encode = ENCODING_TEXTXML; } else { globals.encode = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE; } } else if (!strcasecmp(var, "retries") && !zstr(val)) { globals.retries = (uint32_t) atoi(val); } else if (!strcasecmp(var, "rotate") && !zstr(val)) { globals.rotate = switch_true(val); } else if (!strcasecmp(var, "log-dir")) { if (zstr(val)) { globals.base_log_dir = switch_core_sprintf(globals.pool, "%s%sxml_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); } else { if (switch_is_file_path(val)) { globals.base_log_dir = switch_core_strdup(globals.pool, val); } else { globals.base_log_dir = switch_core_sprintf(globals.pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, val); } } } else if (!strcasecmp(var, "err-log-dir")) { if (zstr(val)) { globals.base_err_log_dir = switch_core_sprintf(globals.pool, "%s%sxml_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); } else { if (switch_is_file_path(val)) { globals.base_err_log_dir = switch_core_strdup(globals.pool, val); } else { globals.base_err_log_dir = switch_core_sprintf(globals.pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, val); } } } else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) { globals.enable_cacert_check = 1; } else if (!strcasecmp(var, "ssl-cert-path")) { globals.ssl_cert_file = val; } else if (!strcasecmp(var, "ssl-key-path")) { globals.ssl_key_file = val; } else if (!strcasecmp(var, "ssl-key-password")) { globals.ssl_key_password = val; } else if (!strcasecmp(var, "ssl-version")) { globals.ssl_version = val; } else if (!strcasecmp(var, "ssl-cacert-file")) { globals.ssl_cacert_file = val; } else if (!strcasecmp(var, "enable-ssl-verifyhost") && switch_true(val)) { globals.enable_ssl_verifyhost = 1; } else if (!strcasecmp(var, "auth-scheme")) { if (*val == '=') { globals.auth_scheme = 0; val++; } if (!strcasecmp(val, "basic")) { globals.auth_scheme |= CURLAUTH_BASIC; } else if (!strcasecmp(val, "digest")) { globals.auth_scheme |= CURLAUTH_DIGEST; } else if (!strcasecmp(val, "NTLM")) { globals.auth_scheme |= CURLAUTH_NTLM; } else if (!strcasecmp(val, "GSS-NEGOTIATE")) { globals.auth_scheme |= CURLAUTH_GSSNEGOTIATE; } else if (!strcasecmp(val, "any")) { globals.auth_scheme = CURLAUTH_ANY; } } } if (zstr(globals.base_err_log_dir)) { if (!zstr(globals.base_log_dir)) { globals.base_err_log_dir = switch_core_strdup(globals.pool, globals.base_log_dir); } else { globals.base_err_log_dir = switch_core_sprintf(globals.pool, "%s%sxml_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); } } } if (globals.retries < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retries is negative, setting to 0\n"); globals.retries = 0; } if (globals.retries && globals.delay <= 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retries set but delay 0 setting to 5 seconds\n"); globals.delay = 5; } globals.retries++; set_xml_cdr_log_dirs(); switch_xml_free(xml); if (status == SWITCH_STATUS_SUCCESS) { switch_curl_init(); } return status; } SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_cdr_shutdown) { globals.shutdown = 1; switch_safe_free(globals.log_dir); switch_safe_free(globals.err_log_dir); switch_event_unbind(&globals.node); switch_core_remove_state_handler(&state_handlers); switch_thread_rwlock_destroy(globals.log_path_lock); switch_curl_destroy(); return SWITCH_STATUS_SUCCESS; }
static switch_status_t channel_on_soft_execute(switch_core_session_t *session) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n"); return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *bug, switch_frame_t *frame, switch_bool_t fill) { switch_size_t bytes = 0, datalen = 0; int16_t *dp, *fp; uint32_t x; size_t rlen = 0; size_t wlen = 0; uint32_t blen; switch_codec_implementation_t read_impl = { 0 }; int16_t *tp; switch_size_t do_read = 0, do_write = 0; int fill_read = 0, fill_write = 0; switch_core_session_get_read_impl(bug->session, &read_impl); bytes = read_impl.decoded_bytes_per_packet; #ifdef TESTINGONLY if (0 && bug->session->recur_buffer_len) { frame->datalen = bug->session->recur_buffer_len; frame->samples = bug->session->recur_buffer_len / sizeof(int16_t); frame->rate = read_impl.actual_samples_per_second; frame->codec = NULL; memcpy(frame->data, bug->session->recur_buffer, bug->session->recur_buffer_len); return SWITCH_STATUS_SUCCESS; } #endif if (frame->buflen < bytes) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "%s frame buffer too small!\n", switch_channel_get_name(bug->session->channel)); return SWITCH_STATUS_FALSE; } if ((!bug->raw_read_buffer && (!bug->raw_write_buffer || !switch_test_flag(bug, SMBF_WRITE_STREAM)))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "%s Buffer Error (raw_read_buffer=%p, raw_write_buffer=%p, read=%s, write=%s)\n", switch_channel_get_name(bug->session->channel), (void *)bug->raw_read_buffer, (void *)bug->raw_write_buffer, switch_test_flag(bug, SMBF_READ_STREAM) ? "yes" : "no", switch_test_flag(bug, SMBF_WRITE_STREAM) ? "yes" : "no"); return SWITCH_STATUS_FALSE; } frame->flags = 0; frame->datalen = 0; if (switch_test_flag(bug, SMBF_READ_STREAM)) { switch_mutex_lock(bug->read_mutex); do_read = switch_buffer_inuse(bug->raw_read_buffer); switch_mutex_unlock(bug->read_mutex); } if (switch_test_flag(bug, SMBF_WRITE_STREAM)) { switch_mutex_lock(bug->write_mutex); do_write = switch_buffer_inuse(bug->raw_write_buffer); switch_mutex_unlock(bug->write_mutex); } if (bug->record_frame_size && bug->record_pre_buffer_max && (do_read || do_write) && bug->record_pre_buffer_count < bug->record_pre_buffer_max) { bug->record_pre_buffer_count++; return SWITCH_STATUS_FALSE; } if (!bug->record_frame_size) { if (do_read && do_write) { switch_size_t frame_size; switch_codec_implementation_t read_impl = { 0 }; switch_codec_implementation_t other_read_impl = { 0 }; switch_core_session_t *other_session; switch_core_session_get_read_impl(bug->session, &read_impl); frame_size = read_impl.decoded_bytes_per_packet; if (switch_core_session_get_partner(bug->session, &other_session) == SWITCH_STATUS_SUCCESS) { switch_core_session_get_read_impl(other_session, &other_read_impl); switch_core_session_rwunlock(other_session); if (read_impl.actual_samples_per_second == other_read_impl.actual_samples_per_second) { if (read_impl.decoded_bytes_per_packet < other_read_impl.decoded_bytes_per_packet) { frame_size = other_read_impl.decoded_bytes_per_packet; } } else { if (read_impl.decoded_bytes_per_packet > other_read_impl.decoded_bytes_per_packet) { frame_size = other_read_impl.decoded_bytes_per_packet; } } } bug->record_frame_size = frame_size; } } if (bug->record_frame_size) { if ((do_read && do_read < bug->record_frame_size) || (do_write && do_write < bug->record_frame_size)) { return SWITCH_STATUS_FALSE; } if (do_read && do_read > bug->record_frame_size) { do_read = bug->record_frame_size; } if (do_write && do_write > bug->record_frame_size) { do_write = bug->record_frame_size; } } fill_read = !do_read; fill_write = !do_write; if (fill_read && fill_write) { return SWITCH_STATUS_FALSE; } if (do_read && do_read > SWITCH_RECOMMENDED_BUFFER_SIZE) { do_read = 1280; } if (do_write && do_write > SWITCH_RECOMMENDED_BUFFER_SIZE) { do_write = 1280; } if (do_read) { switch_mutex_lock(bug->read_mutex); frame->datalen = (uint32_t) switch_buffer_read(bug->raw_read_buffer, frame->data, do_read); if (frame->datalen != do_read) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "Framing Error Reading!\n"); switch_core_media_bug_flush(bug); switch_mutex_unlock(bug->read_mutex); return SWITCH_STATUS_FALSE; } switch_mutex_unlock(bug->read_mutex); } else if (fill_read) { frame->datalen = bytes; memset(frame->data, 255, frame->datalen); } if (do_write) { switch_assert(bug->raw_write_buffer); switch_mutex_lock(bug->write_mutex); datalen = (uint32_t) switch_buffer_read(bug->raw_write_buffer, bug->data, do_write); if (datalen != do_write) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "Framing Error Writing!\n"); switch_core_media_bug_flush(bug); switch_mutex_unlock(bug->write_mutex); return SWITCH_STATUS_FALSE; } switch_mutex_unlock(bug->write_mutex); } else if (fill_write) { datalen = bytes; memset(bug->data, 255, datalen); } tp = bug->tmp; dp = (int16_t *) bug->data; fp = (int16_t *) frame->data; rlen = frame->datalen / 2; wlen = datalen / 2; blen = bytes / 2; if (switch_test_flag(bug, SMBF_STEREO)) { int16_t *left, *right; size_t left_len, right_len; if (switch_test_flag(bug, SMBF_STEREO_SWAP)) { left = dp; /* write stream */ left_len = wlen; right = fp; /* read stream */ right_len = rlen; } else { left = fp; /* read stream */ left_len = rlen; right = dp; /* write stream */ right_len = wlen; } for (x = 0; x < blen; x++) { if (x < left_len) { *(tp++) = *(left + x); } else { *(tp++) = 0; } if (x < right_len) { *(tp++) = *(right + x); } else { *(tp++) = 0; } } memcpy(frame->data, bug->tmp, bytes * 2); } else { for (x = 0; x < blen; x++) { int32_t w = 0, r = 0, z = 0; if (x < rlen) { r = (int32_t) * (fp + x); } if (x < wlen) { w = (int32_t) * (dp + x); } z = w + r; if (z > SWITCH_SMAX || z < SWITCH_SMIN) { if (r) z += (r/2); if (w) z += (w/2); } switch_normalize_to_16bit(z); *(fp + x) = (int16_t) z; } } frame->datalen = bytes; frame->samples = bytes / sizeof(int16_t); frame->rate = read_impl.actual_samples_per_second; frame->codec = NULL; if (fill_read && fill_write) { return SWITCH_STATUS_BREAK; } if (fill_read || fill_write) { return SWITCH_STATUS_BREAK; } memcpy(bug->session->recur_buffer, frame->data, frame->datalen); bug->session->recur_buffer_len = frame->datalen; return SWITCH_STATUS_SUCCESS; }
static switch_status_t channel_on_exchange_media(switch_core_session_t *session) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n"); return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *result) { this_check(SWITCH_STATUS_FALSE); sanity_check(SWITCH_STATUS_FALSE); if (zstr(result)) { return SWITCH_STATUS_SUCCESS; } if (fhp) { if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { return SWITCH_STATUS_FALSE; } if (!strncasecmp(result, "speed", 5)) { char *p; if ((p = strchr(result, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { step = 1; } fhp->speed += step; } else { int speed = atoi(p); fhp->speed = speed; } return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; } else if (!strncasecmp(result, "volume", 6)) { char *p; if ((p = strchr(result, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { step = 1; } fhp->vol += step; } else { int vol = atoi(p); fhp->vol = vol; } return SWITCH_STATUS_SUCCESS; } if (fhp->vol) { switch_normalize_volume(fhp->vol); } return SWITCH_STATUS_FALSE; } else if (!strcasecmp(result, "pause")) { if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) { switch_clear_flag(fhp, SWITCH_FILE_PAUSE); } else { switch_set_flag(fhp, SWITCH_FILE_PAUSE); } return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(result, "stop")) { return SWITCH_STATUS_FALSE; } else if (!strcasecmp(result, "truncate")) { switch_core_file_truncate(fhp, 0); } else if (!strcasecmp(result, "restart")) { unsigned int pos = 0; fhp->speed = 0; switch_core_file_seek(fhp, &pos, 0, SEEK_SET); return SWITCH_STATUS_SUCCESS; } else if (!strncasecmp(result, "seek", 4)) { switch_codec_t *codec; unsigned int samps = 0; unsigned int pos = 0; char *p; codec = switch_core_session_get_read_codec(session); if ((p = strchr(result, ':'))) { p++; if (*p == '+' || *p == '-') { int step; int32_t target; if (!(step = atoi(p))) { step = 1000; } samps = step * (codec->implementation->samples_per_second / 1000); target = (int32_t)fhp->pos + samps; if (target < 0) { target = 0; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(fhp, &pos, target, SEEK_SET); } else { samps = atoi(p) * (codec->implementation->samples_per_second / 1000); if (samps < 0) { samps = 0; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); switch_core_file_seek(fhp, &pos, samps, SEEK_SET); } } return SWITCH_STATUS_SUCCESS; } } if (!strcmp(result, "true") || !strcmp(result, "undefined")) { return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
SWITCH_DECLARE(void) console_clean_log(char *msg) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN,SWITCH_LOG_DEBUG, "%s", switch_str_nil(msg)); }
int ip_addr(char *ip4addr, char *interface, cmd_t cmd) { struct nl_handle *nlh = NULL; struct rtnl_addr *addr = NULL; struct nl_addr *nl_addr = NULL; uint32_t binaddr = 0; int iface_idx = -1; int err,ret = 0; if (init_handle(&nlh) != 0) { return -1; } iface_idx = if_nametoindex(interface); if (iface_idx < 0) { return -1; } addr = rtnl_addr_alloc (); if (!addr) { return -1; } if (inet_pton(AF_INET, ip4addr, &binaddr) == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not valid ip address\n"); ret = -1; goto out; } nl_addr = nl_addr_build (AF_INET, &binaddr, sizeof(binaddr)); if (!nl_addr) { ret = -1; goto out; } rtnl_addr_set_local (addr, nl_addr); nl_addr_put (nl_addr); rtnl_addr_set_ifindex (addr, iface_idx); switch (cmd) { case ADD_IP: err = rtnl_addr_add (nlh, addr, 0); if ( err == -17 ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s is already on %s interface\n", ip4addr, interface); ret = 0; } else if ( err < 0 ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error %d returned from rtnl_addr_add():\n%s\n", err, nl_geterror()); ret = -1; } else { ret = 0; } break; case DEL_IP: err = rtnl_addr_delete (nlh, addr, 0); if (err == -99) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s is not present on %s interface\n", ip4addr, interface); ret = 0; } else if (err < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error %d returned from rtnl_addr_delete():\n%s\n", err, nl_geterror()); ret = -1; } else { ret = 0; } break; } out: if (addr) { rtnl_addr_put (addr); } if (nlh) { nl_close(nlh); nl_handle_destroy(nlh); } return ret; }
static switch_status_t set_xml_cdr_log_dirs() { switch_time_exp_t tm; char *path = NULL; char date[80] = ""; switch_size_t retsize; switch_status_t status = SWITCH_STATUS_SUCCESS, dir_status; switch_time_exp_lt(&tm, switch_micro_time_now()); switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d-%H-%M-%S", &tm); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rotating log file paths\n"); if (!zstr(globals.base_log_dir)) { if (globals.rotate) { if ((path = switch_mprintf("%s%s%s", globals.base_log_dir, SWITCH_PATH_SEPARATOR, date))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rotating log file path to %s\n", path); dir_status = SWITCH_STATUS_SUCCESS; if (switch_directory_exists(path, globals.pool) != SWITCH_STATUS_SUCCESS) { dir_status = switch_dir_make(path, SWITCH_FPROT_OS_DEFAULT, globals.pool); } if (dir_status == SWITCH_STATUS_SUCCESS) { switch_thread_rwlock_wrlock(globals.log_path_lock); switch_safe_free(globals.log_dir); globals.log_dir = path; switch_thread_rwlock_unlock(globals.log_path_lock); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new mod_xml_cdr log_dir path\n"); switch_safe_free(path); status = SWITCH_STATUS_FALSE; } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to generate new mod_xml_cdr log_dir path\n"); status = SWITCH_STATUS_FALSE; } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Setting log file path to %s\n", globals.base_log_dir); if ((path = switch_safe_strdup(globals.base_log_dir))) { switch_thread_rwlock_wrlock(globals.log_path_lock); switch_safe_free(globals.log_dir); globals.log_dir = path; switch_thread_rwlock_unlock(globals.log_path_lock); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set log_dir path\n"); status = SWITCH_STATUS_FALSE; } } } if (!zstr(globals.base_err_log_dir)) { if (globals.rotate) { if ((path = switch_mprintf("%s%s%s", globals.base_err_log_dir, SWITCH_PATH_SEPARATOR, date))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Rotating err log file path to %s\n", path); dir_status = SWITCH_STATUS_SUCCESS; if (switch_directory_exists(path, globals.pool) != SWITCH_STATUS_SUCCESS) { dir_status = switch_dir_make(path, SWITCH_FPROT_OS_DEFAULT, globals.pool); } if (dir_status == SWITCH_STATUS_SUCCESS) { switch_thread_rwlock_wrlock(globals.log_path_lock); switch_safe_free(globals.err_log_dir); globals.err_log_dir = path; switch_thread_rwlock_unlock(globals.log_path_lock); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new mod_xml_cdr err_log_dir path\n"); switch_safe_free(path); status = SWITCH_STATUS_FALSE; } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to generate new mod_xml_cdr err_log_dir path\n"); status = SWITCH_STATUS_FALSE; } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Setting err log file path to %s\n", globals.base_err_log_dir); if ((path = switch_safe_strdup(globals.base_err_log_dir))) { switch_thread_rwlock_wrlock(globals.log_path_lock); switch_safe_free(globals.err_log_dir); globals.err_log_dir = path; switch_thread_rwlock_unlock(globals.log_path_lock); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set err_log_dir path\n"); status = SWITCH_STATUS_FALSE; } } } return status; }
/** * open next file for reading * @param handle the file handle */ static switch_status_t next_file(switch_file_handle_t *handle) { struct rayo_file_context *context = handle->private_info; struct output_component *output = context->component ? OUTPUT_COMPONENT(context->component) : NULL; top: if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) { switch_core_file_close(&context->fh); } if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { /* unsupported */ return SWITCH_STATUS_FALSE; } if (!context->cur_doc) { context->cur_doc = iks_find(output->document, "document"); if (!context->cur_doc) { iks_delete(output->document); output->document = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing <document>\n"); return SWITCH_STATUS_FALSE; } } else { context->cur_doc = iks_next_tag(context->cur_doc); } /* done? */ if (!context->cur_doc) { if (output->repeat_times == 0 || ++context->play_count < output->repeat_times) { /* repeat all document(s) */ if (!output->repeat_interval) { goto top; } } else { /* no more files to play */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Done playing\n"); return SWITCH_STATUS_FALSE; } } if (!context->cur_doc) { /* play silence between repeats */ switch_safe_free(context->ssml); context->ssml = switch_mprintf("silence_stream://%i", output->repeat_interval); } else { /* play next document */ iks *speak = NULL; switch_safe_free(context->ssml); context->ssml = NULL; speak = iks_find(context->cur_doc, "speak"); if (speak) { /* <speak> is child node */ char *ssml_str = iks_string(NULL, speak); if (zstr(output->renderer)) { /* FS must parse the SSML */ context->ssml = switch_mprintf("ssml://%s", ssml_str); } else { /* renderer will parse the SSML */ context->ssml = switch_mprintf("tts://%s||%s", output->renderer, ssml_str); } iks_free(ssml_str); } else if (iks_has_children(context->cur_doc)) { /* check if <speak> is in CDATA */ const char *ssml_str = NULL; iks *ssml = iks_child(context->cur_doc); if (ssml && iks_type(ssml) == IKS_CDATA) { ssml_str = iks_cdata(ssml); } if (zstr(ssml_str)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing <document> CDATA\n"); return SWITCH_STATUS_FALSE; } if (zstr(output->renderer)) { /* FS must parse the SSML */ context->ssml = switch_mprintf("ssml://%s", ssml_str); } else { /* renderer will parse the SSML */ context->ssml = switch_mprintf("tts://%s||%s", output->renderer, ssml_str); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing <speak>\n"); return SWITCH_STATUS_FALSE; } } if (switch_core_file_open(&context->fh, context->ssml, handle->channels, handle->samplerate, handle->flags, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Failed to open %s\n", context->ssml); goto top; } handle->samples = context->fh.samples; handle->format = context->fh.format; handle->sections = context->fh.sections; handle->seekable = context->fh.seekable; handle->speed = context->fh.speed; handle->vol = context->fh.vol; handle->offset_pos = context->fh.offset_pos; handle->interval = context->fh.interval; if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) { switch_set_flag(handle, SWITCH_FILE_NATIVE); } else { switch_clear_flag(handle, SWITCH_FILE_NATIVE); } return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(int) switch_regex_perform(const char *field, const char *expression, switch_regex_t **new_re, int *ovector, uint32_t olen) { const char *error = NULL; int erroffset = 0; pcre *re = NULL; int match_count = 0; char *tmp = NULL; uint32_t flags = 0; char abuf[256] = ""; if (!(field && expression)) { return 0; } if (*expression == '_') { if (switch_ast2regex(expression + 1, abuf, sizeof(abuf))) { expression = abuf; } } if (*expression == '/') { char *opts = NULL; tmp = strdup(expression + 1); assert(tmp); if ((opts = strrchr(tmp, '/'))) { *opts++ = '\0'; } else { goto end; } expression = tmp; if (opts) { if (strchr(opts, 'i')) { flags |= PCRE_CASELESS; } if (strchr(opts, 's')) { flags |= PCRE_DOTALL; } } } re = pcre_compile(expression, /* the pattern */ flags, /* default options */ &error, /* for error message */ &erroffset, /* for error offset */ NULL); /* use default character tables */ if (error) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "COMPILE ERROR: %d [%s][%s]\n", erroffset, error, expression); switch_regex_safe_free(re); goto end; } match_count = pcre_exec(re, /* result of pcre_compile() */ NULL, /* we didn't study the pattern */ field, /* the subject string */ (int) strlen(field), /* the length of the subject string */ 0, /* start at offset 0 in the subject */ 0, /* default options */ ovector, /* vector of integers for substring information */ olen); /* number of elements (NOT size in bytes) */ if (match_count <= 0) { switch_regex_safe_free(re); match_count = 0; } *new_re = (switch_regex_t *) re; end: switch_safe_free(tmp); return match_count; }
/** * Process fileman command */ static switch_status_t fileman_process_cmd(const char *cmd, switch_file_handle_t *fhp) { if (zstr(cmd)) { return SWITCH_STATUS_SUCCESS; } if (fhp) { if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { return SWITCH_STATUS_FALSE; } if (!strncasecmp(cmd, "speed", 5)) { char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { if (*p == '+') { step = 1; } else { step = -1; } } fhp->speed += step; } else { int speed = atoi(p); fhp->speed = speed; } return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; } else if (!strncasecmp(cmd, "volume", 6)) { char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; if (!(step = atoi(p))) { if (*p == '+') { step = 1; } else { step = -1; } } fhp->vol += step; } else { int vol = atoi(p); fhp->vol = vol; } return SWITCH_STATUS_SUCCESS; } if (fhp->vol) { switch_normalize_volume(fhp->vol); } return SWITCH_STATUS_FALSE; } else if (!strcasecmp(cmd, "pause")) { switch_set_flag(fhp, SWITCH_FILE_PAUSE); return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(cmd, "resume")) { switch_clear_flag(fhp, SWITCH_FILE_PAUSE); return SWITCH_STATUS_SUCCESS; } else if (!strcasecmp(cmd, "stop")) { switch_set_flag(fhp, SWITCH_FILE_DONE); return SWITCH_STATUS_FALSE; } else if (!strcasecmp(cmd, "truncate")) { switch_core_file_truncate(fhp, 0); } else if (!strcasecmp(cmd, "restart")) { unsigned int pos = 0; fhp->speed = 0; switch_core_file_seek(fhp, &pos, 0, SEEK_SET); return SWITCH_STATUS_SUCCESS; } else if (!strncasecmp(cmd, "seek", 4)) { unsigned int samps = 0; unsigned int pos = 0; char *p; if ((p = strchr(cmd, ':'))) { p++; if (*p == '+' || *p == '-') { int step; int32_t target; if (!(step = atoi(p))) { if (*p == '+') { step = 1000; } else { step = -1000; } } samps = step * (fhp->samplerate / 1000); target = (int32_t)fhp->pos + samps; if (target < 0) { target = 0; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "seek to position %d\n", target); switch_core_file_seek(fhp, &pos, target, SEEK_SET); } else { samps = switch_atoui(p) * (fhp->samplerate / 1000); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "seek to position %d\n", samps); switch_core_file_seek(fhp, &pos, samps, SEEK_SET); } } return SWITCH_STATUS_SUCCESS; } } if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) { return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
static http_data_t *do_lookup_url(switch_memory_pool_t *pool, const char *url, const char *method, const char *data, const char *content_type, curl_options_t *options) { switch_CURL *curl_handle = NULL; long httpRes = 0; http_data_t *http_data = NULL; switch_curl_slist_t *headers = NULL; struct data_stream dstream = { NULL }; http_data = switch_core_alloc(pool, sizeof(http_data_t)); memset(http_data, 0, sizeof(http_data_t)); http_data->pool = pool; http_data->max_bytes = 64000; SWITCH_STANDARD_STREAM(http_data->stream); if (!method) { method = "get"; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "method: %s, url: %s, content-type: %s\n", method, url, content_type); curl_handle = switch_curl_easy_init(); if (options) { if (options->connect_timeout) { switch_curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, options->connect_timeout); } if (options->timeout) { switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, options->timeout); } } if (!strncasecmp(url, "https", 5)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Not verifying TLS cert for %s; connection is not secure\n", url); switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); } if (!strcasecmp(method, "head")) { switch_curl_easy_setopt(curl_handle, CURLOPT_NOBODY, 1); } else if (!strcasecmp(method, "post")) { switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, strlen(data)); switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, (void *) data); if (content_type) { char *ct = switch_mprintf("Content-Type: %s", content_type); headers = switch_curl_slist_append(headers, ct); switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); switch_safe_free(ct); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Post data: %s\n", data); } else if (!strcasecmp(method, "delete")) { switch_curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "DELETE"); switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, strlen(data)); switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, (void *) data); if (content_type) { char *ct = switch_mprintf("Content-Type: %s", content_type); headers = switch_curl_slist_append(headers, ct); switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); switch_safe_free(ct); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DELETE data: %s\n", data); } else if (!strcasecmp(method, "put")) { dstream.data = data; dstream.length = strlen(data); switch_curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1); switch_curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback); switch_curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)dstream.length); switch_curl_easy_setopt(curl_handle, CURLOPT_READDATA, (void *) &dstream); if (content_type) { char *ct = switch_mprintf("Content-Type: %s", content_type); headers = switch_curl_slist_append(headers, ct); headers = switch_curl_slist_append(headers, "Expect:"); switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); switch_safe_free(ct); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PUT data: %s\n", data); } else { switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1); } switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 15); switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY); switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url); switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback); switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) http_data); switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback); switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *) http_data); switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-curl/1.0"); switch_curl_easy_perform(curl_handle); switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes); switch_curl_easy_cleanup(curl_handle); switch_curl_slist_free_all(headers); if (http_data->stream.data && !zstr((char *) http_data->stream.data) && strcmp(" ", http_data->stream.data)) { http_data->http_response = switch_core_strdup(pool, http_data->stream.data); } http_data->http_response_code = httpRes; switch_safe_free(http_data->stream.data); return http_data; }
switch_status_t load_agent(const char *agent_name) { switch_xml_t x_agents, x_agent, cfg, xml; 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 SWITCH_STATUS_FALSE; } if (!(x_agents = switch_xml_child(cfg, "agents"))) { goto end; } if ((x_agent = switch_xml_find_child(x_agents, "agent", "name", agent_name))) { const char *type = switch_xml_attr(x_agent, "type"); const char *contact = switch_xml_attr(x_agent, "contact"); const char *status = switch_xml_attr(x_agent, "status"); const char *max_no_answer = switch_xml_attr(x_agent, "max-no-answer"); const char *wrap_up_time = switch_xml_attr(x_agent, "wrap-up-time"); const char *reject_delay_time = switch_xml_attr(x_agent, "reject-delay-time"); const char *busy_delay_time = switch_xml_attr(x_agent, "busy-delay-time"); const char *no_answer_delay_time = switch_xml_attr(x_agent, "no-answer-delay-time"); if (type) { cc_status_t res = cc_agent_add(agent_name, type); // For HA, only add new agent, DO NOT update or DELETE. if (res == CC_STATUS_AGENT_ALREADY_EXIST) { goto end; } if (res == CC_STATUS_SUCCESS) { if (contact) { cc_agent_update("contact", contact, agent_name); } if (status) { cc_agent_update("status", status, agent_name); } if (wrap_up_time) { cc_agent_update("wrap_up_time", wrap_up_time, agent_name); } if (max_no_answer) { cc_agent_update("max_no_answer", max_no_answer, agent_name); } if (reject_delay_time) { cc_agent_update("reject_delay_time", reject_delay_time, agent_name); } if (busy_delay_time) { cc_agent_update("busy_delay_time", busy_delay_time, agent_name); } if (no_answer_delay_time) { cc_agent_update("no_answer_delay_time", no_answer_delay_time, agent_name); } /* if (type && res == CC_STATUS_AGENT_ALREADY_EXIST) { cc_agent_update("type", type, agent_name); }*/ } } } end: if (xml) { switch_xml_free(xml); } return SWITCH_STATUS_SUCCESS; }
static char *print_json(switch_memory_pool_t *pool, http_data_t *http_data) { cJSON *top = cJSON_CreateObject(), *headers = cJSON_CreateArray(); char *data = NULL; char tmp[32], *f = NULL; switch_curl_slist_t *header = http_data->headers; if(!top || !headers) { cJSON_Delete(headers); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to alloc memory for cJSON structures.\n"); goto curl_json_output_end; } switch_snprintf(tmp, sizeof(tmp), "%ld", http_data->http_response_code); cJSON_AddItemToObject(top, "status_code", cJSON_CreateString(tmp)); if (http_data->http_response) { cJSON_AddItemToObject(top, "body", cJSON_CreateString(http_data->http_response)); } /* parse header data */ while (header) { cJSON *obj = NULL; /* remove trailing \r */ if ((data = strrchr(header->data, '\r'))) { *data = '\0'; } if (zstr(header->data)) { header = header->next; continue; } if ((data = strchr(header->data, ':'))) { *data = '\0'; data++; while (*data == ' ' && *data != '\0') { data++; } obj = cJSON_CreateObject(); cJSON_AddItemToObject(obj, "key", cJSON_CreateString(header->data)); cJSON_AddItemToObject(obj, "value", cJSON_CreateString(data)); cJSON_AddItemToArray(headers, obj); } else { if (!strncmp("HTTP", header->data, 4)) { char *argv[3] = { 0 }; int argc; if ((argc = switch_separate_string(header->data, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { if (argc > 2) { cJSON_AddItemToObject(top, "version", cJSON_CreateString(argv[0])); cJSON_AddItemToObject(top, "phrase", cJSON_CreateString(argv[2])); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unparsable header: argc: %d\n", argc); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Starts with HTTP but not parsable: %s\n", header->data); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unparsable header: %s\n", header->data); } } header = header->next; } cJSON_AddItemToObject(top, "headers", headers); f = cJSON_PrintUnformatted(top); data = switch_core_strdup(pool, f); switch_safe_free(f); curl_json_output_end: cJSON_Delete(top); /* should free up all children */ return data; }
void * SWITCH_THREAD_FUNC mod_amqp_command_thread(switch_thread_t *thread, void *data) { mod_amqp_command_profile_t *profile = (mod_amqp_command_profile_t *) data; while (profile->running) { amqp_queue_declare_ok_t *recv_queue; amqp_bytes_t queueName = { 0, NULL }; /* Ensure we have an AMQP connection */ if (!profile->conn_active) { switch_status_t status; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Amqp no connection- reconnecting...\n"); status = mod_amqp_connection_open(profile->conn_root, &(profile->conn_active), profile->name, profile->custom_attr); if ( status != SWITCH_STATUS_SUCCESS ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Profile[%s] failed to connect with code(%d), sleeping for %dms\n", profile->name, status, profile->reconnect_interval_ms); switch_sleep(profile->reconnect_interval_ms * 1000); continue; } /* Check if exchange already exists */ amqp_exchange_declare(profile->conn_active->state, 1, amqp_cstring_bytes(profile->exchange), amqp_cstring_bytes("topic"), 0, /* passive */ 1, /* durable */ amqp_empty_table); if (mod_amqp_log_if_amqp_error(amqp_get_rpc_reply(profile->conn_active->state), "Checking for command exchange")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Profile[%s] failed to create missing command exchange", profile->name); continue; } /* Ensure we have a queue */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Creating command queue"); recv_queue = amqp_queue_declare(profile->conn_active->state, // state 1, // channel profile->queue ? amqp_cstring_bytes(profile->queue) : amqp_empty_bytes, // queue name 0, 0, // passive, durable 0, 1, // exclusive, auto-delete amqp_empty_table); // args if (mod_amqp_log_if_amqp_error(amqp_get_rpc_reply(profile->conn_active->state), "Declaring queue")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Profile[%s] failed to connect with code(%d), sleeping for %dms\n", profile->name, status, profile->reconnect_interval_ms); switch_sleep(profile->reconnect_interval_ms * 1000); continue; } if (queueName.bytes) { amqp_bytes_free(queueName); } queueName = amqp_bytes_malloc_dup(recv_queue->queue); if (!queueName.bytes) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory while copying queue name"); break; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Created command queue %.*s", (int)queueName.len, (char *)queueName.bytes); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Binding command queue to exchange %s", profile->exchange); /* Bind the queue to the exchange */ amqp_queue_bind(profile->conn_active->state, // state 1, // channel queueName, // queue amqp_cstring_bytes(profile->exchange), // exchange amqp_cstring_bytes(profile->binding_key), // routing key amqp_empty_table); // args if (mod_amqp_log_if_amqp_error(amqp_get_rpc_reply(profile->conn_active->state), "Binding queue")) { mod_amqp_connection_close(profile->conn_active); profile->conn_active = NULL; switch_sleep(profile->reconnect_interval_ms * 1000); continue; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Amqp reconnect successful- connected\n"); continue; } // Start a command amqp_basic_consume(profile->conn_active->state, // state 1, // channel queueName, // queue amqp_empty_bytes, // command tag 0, 1, 0, // no_local, no_ack, exclusive amqp_empty_table); // args if (mod_amqp_log_if_amqp_error(amqp_get_rpc_reply(profile->conn_active->state), "Creating a command")) { mod_amqp_connection_close(profile->conn_active); profile->conn_active = NULL; switch_sleep(profile->reconnect_interval_ms * 1000); continue; } while (profile->running && profile->conn_active) { amqp_rpc_reply_t res; amqp_envelope_t envelope; struct timeval timeout = {0}; char command[1024]; enum ECommandFormat { COMMAND_FORMAT_UNKNOWN, COMMAND_FORMAT_PLAINTEXT } commandFormat = COMMAND_FORMAT_PLAINTEXT; char *fs_resp_exchange = NULL, *fs_resp_key = NULL; amqp_maybe_release_buffers(profile->conn_active->state); timeout.tv_usec = 500 * 1000; res = amqp_consume_message(profile->conn_active->state, &envelope, &timeout, 0); if (res.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION) { if (res.library_error == AMQP_STATUS_UNEXPECTED_STATE) { /* Unexpected frame. Discard it then continue */ amqp_frame_t decoded_frame; amqp_simple_wait_frame(profile->conn_active->state, &decoded_frame); } if (res.library_error == AMQP_STATUS_SOCKET_ERROR) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A socket error occurred. Tearing down and reconnecting\n"); break; } if (res.library_error == AMQP_STATUS_CONNECTION_CLOSED) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "AMQP connection was closed. Tearing down and reconnecting\n"); break; } if (res.library_error == AMQP_STATUS_TCP_ERROR) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A TCP error occurred. Tearing down and reconnecting\n"); break; } if (res.library_error == AMQP_STATUS_TIMEOUT) { // nop } /* Try consuming again */ continue; } if (res.reply_type != AMQP_RESPONSE_NORMAL) { break; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Delivery:%u, exchange:%.*s routingkey:%.*s\n", (unsigned) envelope.delivery_tag, (int) envelope.exchange.len, (char *) envelope.exchange.bytes, (int) envelope.routing_key.len, (char *) envelope.routing_key.bytes); if (envelope.message.properties._flags & AMQP_BASIC_CONTENT_TYPE_FLAG) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Content-type: %.*s\n", (int) envelope.message.properties.content_type.len, (char *) envelope.message.properties.content_type.bytes); if (strncasecmp("text/plain", envelope.message.properties.content_type.bytes, strlen("text/plain")) == 0) { commandFormat = COMMAND_FORMAT_PLAINTEXT; } else { commandFormat = COMMAND_FORMAT_UNKNOWN; } } if (envelope.message.properties.headers.num_entries) { int x = 0; for ( x = 0; x < envelope.message.properties.headers.num_entries; x++) { char *header_key = (char *)envelope.message.properties.headers.entries[x].key.bytes; char *header_value = (char *)envelope.message.properties.headers.entries[x].value.value.bytes.bytes; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AMQP message custom header key[%s] value[%s]\n", header_key, header_value); if ( !strncmp(header_key, "x-fs-api-resp-exchange", 22)) { fs_resp_exchange = header_value; } else if (!strncmp(header_key, "x-fs-api-resp-key", 17)) { fs_resp_key = header_value; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring unrecognized event header [%s]\n", header_key); } } } if (commandFormat == COMMAND_FORMAT_PLAINTEXT) { switch_stream_handle_t stream = { 0 }; /* Collects the command output */ /* Convert amqp bytes to c-string */ snprintf(command, sizeof(command), "%.*s", (int) envelope.message.body.len, (char *) envelope.message.body.bytes); /* Execute the command */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Executing: %s\n", command); SWITCH_STANDARD_STREAM(stream); if ( fs_resp_exchange && fs_resp_key ) { switch_status_t status = switch_console_execute(command, 0, &stream); mod_amqp_command_response(profile, command, stream, fs_resp_exchange, fs_resp_key, status); } else { if (switch_console_execute(command, 0, &stream) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Remote command failed:\n%s\n", (char *) stream.data); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Remote command succeeded:\n%s\n", (char *) stream.data); } } switch_safe_free(stream.data); } /* Tidy up */ amqp_destroy_envelope(&envelope); } amqp_bytes_free(queueName); queueName.bytes = NULL; mod_amqp_connection_close(profile->conn_active); profile->conn_active = NULL; if (profile->running) { /* We'll reconnect, but sleep to avoid hammering resources */ switch_sleep(500); } } /* Terminate the thread */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Command listener thread stopped\n"); switch_thread_exit(thread, SWITCH_STATUS_SUCCESS); return NULL; }
// This function and do_lookup_url functions could possibly be merged together. Or at least have do_lookup_url call this up as part of the initialization routine as it is a subset of the operations. static void http_sendfile_initialize_curl(http_sendfile_data_t *http_data) { uint8_t count; http_data->curl_handle = curl_easy_init(); if (!strncasecmp(http_data->url, "https", 5)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Not verifying TLS cert for %s; connection is not secure\n", http_data->url); curl_easy_setopt(http_data->curl_handle, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(http_data->curl_handle, CURLOPT_SSL_VERIFYHOST, 0); } /* From the docs: * Optionally, you can provide data to POST using the CURLOPT_READFUNCTION and CURLOPT_READDATA * options but then you must make sure to not set CURLOPT_POSTFIELDS to anything but NULL * curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, strlen(data)); * curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, (void *) data); */ // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Post data: %s\n", data); curl_easy_setopt(http_data->curl_handle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(http_data->curl_handle, CURLOPT_MAXREDIRS, 15); curl_easy_setopt(http_data->curl_handle, CURLOPT_URL, http_data->url); curl_easy_setopt(http_data->curl_handle, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(http_data->curl_handle, CURLOPT_USERAGENT, "freeswitch-curl/1.0"); http_data->sendfile_response = switch_core_alloc(http_data->pool, sizeof(char) * HTTP_SENDFILE_RESPONSE_SIZE); memset(http_data->sendfile_response, 0, sizeof(char) * HTTP_SENDFILE_RESPONSE_SIZE); // Set the function where we will copy out the response body data to curl_easy_setopt(http_data->curl_handle, CURLOPT_WRITEFUNCTION, http_sendfile_response_callback); curl_easy_setopt(http_data->curl_handle, CURLOPT_WRITEDATA, (void *) http_data); /* Add the file to upload as a POST form field */ curl_formadd(&http_data->formpost, &http_data->lastptr, CURLFORM_COPYNAME, http_data->filename_element_name, CURLFORM_FILE, http_data->filename_element, CURLFORM_END); if(!zstr(http_data->extrapost_elements)) { // Now to parse out the individual post element/value pairs char *argv[64] = { 0 }; // Probably don't need 64 but eh does it really use that much memory? uint32_t argc = 0; char *temp_extrapost = switch_core_strdup(http_data->pool, http_data->extrapost_elements); argc = switch_separate_string(temp_extrapost, '&', argv, (sizeof(argv) / sizeof(argv[0]))); for(count = 0; count < argc; count++) { char *argv2[4] = { 0 }; uint32_t argc2 = switch_separate_string(argv[count], '=', argv2, (sizeof(argv2) / sizeof(argv2[0]))); if(argc2 == 2) { switch_url_decode(argv2[0]); switch_url_decode(argv2[1]); curl_formadd(&http_data->formpost, &http_data->lastptr, CURLFORM_COPYNAME, argv2[0], CURLFORM_COPYCONTENTS, argv2[1], CURLFORM_END); } } } /* Fill in the submit field too, even if this isn't really needed */ curl_formadd(&http_data->formpost, &http_data->lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "or_die", CURLFORM_END); /* what URL that receives this POST */ curl_easy_setopt(http_data->curl_handle, CURLOPT_HTTPPOST, http_data->formpost); // This part actually fires off the curl, captures the HTTP response code, and then frees up the handle. curl_easy_perform(http_data->curl_handle); curl_easy_getinfo(http_data->curl_handle, CURLINFO_RESPONSE_CODE, &http_data->http_response_code); curl_easy_cleanup(http_data->curl_handle); // Clean up the form data from POST curl_formfree(http_data->formpost); }
static switch_status_t my_on_reporting(switch_core_session_t *session) { switch_status_t status = SWITCH_STATUS_SUCCESS; switch_channel_t *channel = switch_core_session_get_channel(session); switch_event_header_t *hi; switch_caller_profile_t *caller_profile; switch_hold_record_t *hold_record; switch_app_log_t *app_log; bson cdr; int is_b; int bson_idx, callflow_idx; char idx_buffer[4]; char *tmp; if (globals.shutdown) { return SWITCH_STATUS_SUCCESS; } is_b = channel && switch_channel_get_originator_caller_profile(channel); if (!globals.log_b && is_b) { const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE); if (!switch_true(force_cdr)) { return SWITCH_STATUS_SUCCESS; } } bson_init(&cdr); /* Channel data */ bson_append_start_object(&cdr, "channel_data"); bson_append_string(&cdr, "state", switch_channel_state_name(switch_channel_get_state(channel))); bson_append_string(&cdr, "direction", switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"); bson_append_int(&cdr, "state_number", switch_channel_get_state(channel)); if ((tmp = switch_channel_get_flag_string(channel))) { bson_append_string(&cdr, "flags", tmp); free(tmp); } if ((tmp = switch_channel_get_cap_string(channel))) { bson_append_string(&cdr, "caps", tmp); free(tmp); } bson_append_finish_object(&cdr); /* channel_data */ /* Channel variables */ bson_append_start_object(&cdr, "variables"); if ((hi = switch_channel_variable_first(channel))) { for (; hi; hi = hi->next) { if (!zstr(hi->name) && !zstr(hi->value)) { bson_append_string(&cdr, hi->name, hi->value); } } switch_channel_variable_last(channel); } bson_append_finish_object(&cdr); /* variables */ /* App log */ if ((app_log = switch_core_session_get_app_log(session))) { switch_app_log_t *ap; bson_append_start_array(&cdr, "app_log"); for (ap = app_log, bson_idx = 0; ap; ap = ap->next, bson_idx++) { switch_snprintf(idx_buffer, sizeof(idx_buffer), "%d", bson_idx); bson_append_start_object(&cdr, idx_buffer); bson_append_string(&cdr, "app_name", ap->app); bson_append_string(&cdr, "app_data", switch_str_nil(ap->arg)); bson_append_long(&cdr, "app_stamp", ap->stamp); bson_append_finish_object(&cdr); /* application */ } bson_append_finish_array(&cdr); /* app_log */ } /* Hold */ if ((hold_record = switch_channel_get_hold_record(channel))) { switch_hold_record_t *hr; bson_append_start_array(&cdr, "hold_record"); for (hr = hold_record, bson_idx = 0; hr; hr = hr->next, bson_idx++) { switch_snprintf(idx_buffer, sizeof(idx_buffer), "%d", bson_idx); bson_append_start_object(&cdr, idx_buffer); bson_append_long(&cdr, "on", hr->on); bson_append_long(&cdr, "off", hr->off); if (hr->uuid) { bson_append_string(&cdr, "bridged_to", hr->uuid); } bson_append_finish_object(&cdr); } bson_append_finish_array(&cdr); /* hold_record */ } /* Callflow */ caller_profile = switch_channel_get_caller_profile(channel); /* Start callflow array */ bson_append_start_array(&cdr, "callflow"); callflow_idx = 0; while (caller_profile) { snprintf(idx_buffer, sizeof(idx_buffer), "%d", callflow_idx); bson_append_start_object(&cdr, idx_buffer); if (!zstr(caller_profile->dialplan)) { bson_append_string(&cdr, "dialplan", caller_profile->dialplan); } if (!zstr(caller_profile->profile_index)) { bson_append_string(&cdr, "profile_index", caller_profile->profile_index); } if (caller_profile->caller_extension) { switch_caller_application_t *ap; bson_append_start_object(&cdr, "extension"); bson_append_string(&cdr, "name", switch_str_nil(caller_profile->caller_extension->extension_name)); bson_append_string(&cdr, "number", switch_str_nil(caller_profile->caller_extension->extension_number)); if (caller_profile->caller_extension->current_application) { bson_append_string(&cdr, "current_app", caller_profile->caller_extension->current_application->application_name); } for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) { bson_append_start_object(&cdr, "application"); if (ap == caller_profile->caller_extension->current_application) { bson_append_bool(&cdr, "last_executed", 1); } bson_append_string(&cdr, "app_name", ap->application_name); bson_append_string(&cdr, "app_data", switch_str_nil(ap->application_data)); bson_append_finish_object(&cdr); } if (caller_profile->caller_extension->children) { switch_caller_profile_t *cp = NULL; for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) { if (!cp->caller_extension) { continue; } bson_append_start_object(&cdr, "sub_extensions"); bson_append_start_object(&cdr, "extension"); bson_append_string(&cdr, "name", cp->caller_extension->extension_name); bson_append_string(&cdr, "number", cp->caller_extension->extension_number); bson_append_string(&cdr, "dialplan", cp->dialplan); if (cp->caller_extension->current_application) { bson_append_string(&cdr, "current_app", cp->caller_extension->current_application->application_name); } for (ap = cp->caller_extension->applications; ap; ap = ap->next) { bson_append_start_object(&cdr, "application"); if (ap == cp->caller_extension->current_application) { bson_append_bool(&cdr, "last_executed", 1); } bson_append_string(&cdr, "app_name", ap->application_name); bson_append_string(&cdr, "app_data", switch_str_nil(ap->application_data)); bson_append_finish_object(&cdr); } bson_append_finish_object(&cdr); /* extension */ bson_append_finish_object(&cdr); /* sub_extensions */ } } bson_append_finish_object(&cdr); /* extension */ } bson_append_start_object(&cdr, "caller_profile"); set_bson_profile_data(&cdr, caller_profile); if (caller_profile->origination_caller_profile) { switch_caller_profile_t *cp = NULL; /* Start origination array */ bson_append_start_array(&cdr, "origination"); for (cp = caller_profile->origination_caller_profile, bson_idx = 0; cp; cp = cp->next, bson_idx++) { snprintf(idx_buffer, sizeof(idx_buffer), "%d", bson_idx); bson_append_start_object(&cdr, idx_buffer); set_bson_profile_data(&cdr, cp); bson_append_finish_object(&cdr); } bson_append_finish_object(&cdr); /* origination */ } if (caller_profile->originator_caller_profile) { switch_caller_profile_t *cp = NULL; /* Start originator array */ bson_append_start_array(&cdr, "originator"); for (cp = caller_profile->originator_caller_profile, bson_idx = 0; cp; cp = cp->next, bson_idx++) { snprintf(idx_buffer, sizeof(idx_buffer), "%d", bson_idx); bson_append_start_object(&cdr, idx_buffer); set_bson_profile_data(&cdr, cp); bson_append_finish_object(&cdr); } bson_append_finish_object(&cdr); /* originator */ } if (caller_profile->originatee_caller_profile) { switch_caller_profile_t *cp = NULL; /* Start originatee array */ bson_append_start_array(&cdr, "originatee"); for (cp = caller_profile->originatee_caller_profile, bson_idx = 0; cp; cp = cp->next, bson_idx++) { snprintf(idx_buffer, sizeof(idx_buffer), "%d", bson_idx); bson_append_start_object(&cdr, idx_buffer); set_bson_profile_data(&cdr, cp); bson_append_finish_object(&cdr); } bson_append_finish_object(&cdr); /* originatee */ } bson_append_finish_object(&cdr); /* caller_profile */ /* Timestamps */ if (caller_profile->times) { bson_append_start_object(&cdr, "times"); /* Insert timestamps as long ints (microseconds) to preserve accuracy */ bson_append_long(&cdr, "created_time", caller_profile->times->created); bson_append_long(&cdr, "profile_created_time", caller_profile->times->profile_created); bson_append_long(&cdr, "progress_time", caller_profile->times->progress); bson_append_long(&cdr, "progress_media_time", caller_profile->times->progress_media); bson_append_long(&cdr, "answered_time", caller_profile->times->answered); bson_append_long(&cdr, "bridged_time", caller_profile->times->bridged); bson_append_long(&cdr, "last_hold_time", caller_profile->times->last_hold); bson_append_long(&cdr, "hold_accum_time", caller_profile->times->hold_accum); bson_append_long(&cdr, "hangup_time", caller_profile->times->hungup); bson_append_long(&cdr, "resurrect_time", caller_profile->times->resurrected); bson_append_long(&cdr, "transfer_time", caller_profile->times->transferred); bson_append_finish_object(&cdr); /* times */ } bson_append_finish_object(&cdr); /* callflow */ caller_profile = caller_profile->next; callflow_idx++; } bson_append_finish_array(&cdr); bson_finish(&cdr); switch_mutex_lock(globals.mongo_mutex); if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr, NULL) != MONGO_OK) { if (globals.mongo_conn->err == MONGO_IO_ERROR) { mongo_error_t db_status; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MongoDB connection failed; attempting reconnect...\n"); db_status = mongo_reconnect(globals.mongo_conn); if (db_status != MONGO_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MongoDB reconnect failed with error code %d\n", db_status); status = SWITCH_STATUS_FALSE; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MongoDB connection re-established.\n"); /* Re-authentication is necessary after a reconnect */ if (globals.mongo_username && globals.mongo_password) { status = cdr_mongo_authenticate(); } if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr, NULL) != MONGO_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: %s (error code %d)\n", globals.mongo_conn->errstr, globals.mongo_conn->err); status = SWITCH_STATUS_FALSE; } } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: %s (error code %d)\n", globals.mongo_conn->errstr, globals.mongo_conn->err); status = SWITCH_STATUS_FALSE; } } switch_mutex_unlock(globals.mongo_mutex); bson_destroy(&cdr); return status; }
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; }
SWITCH_DECLARE(switch_status_t) switch_xml_config_parse_event(switch_event_t *event, int count, switch_bool_t reload, switch_xml_config_item_t *instructions) { switch_xml_config_item_t *item; int matched_count = 0; for (item = instructions; item->key; item++) { const char *value = switch_event_get_header(event, item->key); switch_bool_t changed = SWITCH_FALSE; switch_xml_config_callback_t callback = (switch_xml_config_callback_t) item->function; void *ptr = item->ptr; //switch_assert(ptr); if (value) { matched_count++; } if (reload && !switch_test_flag(item, CONFIG_RELOADABLE)) { continue; } if (!value && switch_test_flag(item, CONFIG_REQUIRED)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Required parameter [%s] is missing\n", item->key); return SWITCH_STATUS_FALSE; } switch (item->type) { case SWITCH_CONFIG_INT: { switch_xml_config_int_options_t *int_options = (switch_xml_config_int_options_t *) item->data; int *dest = (int *) ptr; int intval; if (value) { if (switch_is_number(value)) { intval = atoi(value); } else { intval = (int) (intptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%d]\n", value, item->key, intval); } if (int_options) { /* Enforce validation options */ if ((int_options->enforce_min && !(intval >= int_options->min)) || (int_options->enforce_max && !(intval <= int_options->max))) { /* Validation failed, set default */ intval = (int) (intptr_t) item->defaultvalue; /* Then complain */ if (int_options->enforce_min && int_options->enforce_max) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], should be between [%d] and [%d], setting default [%d]\n", value, item->key, int_options->min, int_options->max, intval); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], should be %s [%d], setting default [%d]\n", value, item->key, int_options->enforce_min ? "at least" : "at max", int_options->enforce_min ? int_options->min : int_options->max, intval); } } } } else { intval = (int) (intptr_t) item->defaultvalue; } if (*dest != intval) { *dest = intval; changed = SWITCH_TRUE; } } break; case SWITCH_CONFIG_ATOMIC: { switch_xml_config_atomic_options_t *atomic_options = (switch_xml_config_atomic_options_t *) item->data; switch_atomic_t *dest = (switch_atomic_t *) ptr; uint32_t uintval; if (value) { if (switch_is_number(value)) { uintval = (uint32_t) strtol(value, NULL, 10); } else { uintval = (uint32_t) (uintptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%u]\n", value, item->key, uintval); } if (atomic_options) { /* Enforce validation options */ if ((atomic_options->enforce_min && !(uintval >= atomic_options->min)) || (atomic_options->enforce_max && !(uintval <= atomic_options->max))) { /* Validation failed, set default */ uintval = (uint32_t) (uintptr_t) item->defaultvalue; /* Then complain */ if (atomic_options->enforce_min && atomic_options->enforce_max) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], should be between [%u] and [%u], setting default [%u]\n", value, item->key, atomic_options->min, atomic_options->max, uintval); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], should be %s [%u], setting default [%u]\n", value, item->key, atomic_options->enforce_min ? "at least" : "at max", atomic_options->enforce_min ? atomic_options->min : atomic_options->max, uintval); } } } } else { uintval = (uint32_t) (uintptr_t) item->defaultvalue; } if (switch_atomic_read(dest) != uintval) { switch_atomic_set(dest, uintval); changed = SWITCH_TRUE; } } break; case SWITCH_CONFIG_STRING: { switch_xml_config_string_options_t string_options_default = { 0 }; switch_xml_config_string_options_t *string_options = item->data ? (switch_xml_config_string_options_t *) item->data : &string_options_default; const char *newstring = NULL; /* Perform validation */ if (value) { if (!zstr(string_options->validation_regex)) { if (switch_regex_match(value, string_options->validation_regex) == SWITCH_STATUS_SUCCESS) { newstring = value; /* Regex match, accept value */ } else { newstring = (char *) item->defaultvalue; /* Regex failed */ if (newstring) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%s]\n", value, item->key, newstring); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s]\n", value, item->key); } switch_xml_config_item_print_doc(SWITCH_LOG_ERROR, item); } } else { newstring = value; /* No validation */ } } else { newstring = (char *) item->defaultvalue; } if (string_options->length > 0) { /* We have a preallocated buffer */ char *dest = (char *) ptr; if (newstring) { if (strncasecmp(dest, newstring, string_options->length)) { switch_copy_string(dest, newstring, string_options->length); changed = SWITCH_TRUE; } } else { if (*dest != '\0') { *dest = '\0'; changed = SWITCH_TRUE; } } } else if (string_options->pool) { /* Pool-allocated buffer */ char **dest = (char **) ptr; if (newstring) { if (!*dest || strcmp(*dest, newstring)) { *dest = switch_core_strdup(string_options->pool, newstring); } } else { if (*dest) { changed = SWITCH_TRUE; *dest = NULL; } } } else { /* Dynamically allocated buffer */ char **dest = (char **) ptr; if (newstring) { if (!*dest || strcmp(*dest, newstring)) { switch_safe_free(*dest); *dest = strdup(newstring); changed = SWITCH_TRUE; } } else { if (*dest) { switch_safe_free(*dest); changed = SWITCH_TRUE; } } } } break; case SWITCH_CONFIG_BOOL: { switch_bool_t *dest = (switch_bool_t *) ptr; switch_bool_t newval = SWITCH_FALSE; if (value && switch_true(value)) { newval = SWITCH_TRUE; } else if (value && switch_false(value)) { newval = SWITCH_FALSE; } else if (value) { /* Value isnt true or false */ newval = (switch_bool_t) (intptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%s]\n", value, item->key, newval ? "true" : "false"); switch_xml_config_item_print_doc(SWITCH_LOG_ERROR, item); } else { newval = (switch_bool_t) (intptr_t) item->defaultvalue; } if (*dest != newval) { *dest = newval; changed = SWITCH_TRUE; } } break; case SWITCH_CONFIG_CUSTOM: break; case SWITCH_CONFIG_ENUM: { switch_xml_config_enum_item_t *enum_options = (switch_xml_config_enum_item_t *) item->data; int *dest = (int *) ptr; int newval = 0; switch_status_t lookup_result = SWITCH_STATUS_SUCCESS; if (value) { lookup_result = switch_xml_config_enum_str2int(enum_options, value, &newval); } else { newval = (int) (intptr_t) item->defaultvalue; } if (lookup_result != SWITCH_STATUS_SUCCESS) { newval = (int) (intptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s]\n", value, item->key); switch_xml_config_item_print_doc(SWITCH_LOG_ERROR, item); } if (*dest != newval) { changed = SWITCH_TRUE; *dest = newval; } } break; case SWITCH_CONFIG_FLAG: { int32_t *dest = (int32_t *) ptr; int index = (int) (intptr_t) item->data; int8_t currentval = (int8_t) ! !(*dest & index); int newval = 0; if (value) { newval = switch_true(value); } else { newval = (switch_bool_t) (intptr_t) item->defaultvalue; } if (newval != currentval) { changed = SWITCH_TRUE; if (newval) { *dest |= (1 << index); } else { *dest &= ~(1 << index); } } } break; case SWITCH_CONFIG_FLAGARRAY: { int8_t *dest = (int8_t *) ptr; unsigned int index = (unsigned int) (intptr_t) item->data; int8_t newval = value ? !!switch_true(value) : (int8_t) ((intptr_t) item->defaultvalue); if (dest[index] != newval) { changed = SWITCH_TRUE; dest[index] = newval; } } break; case SWITCH_CONFIG_LAST: break; default: break; } if (callback) { callback(item, value, (reload ? CONFIG_RELOAD : CONFIG_LOAD), changed); } } if (count != matched_count) { /* User made a mistake, find it */ switch_event_header_t *header; for (header = event->headers; header; header = header->next) { switch_bool_t found = SWITCH_FALSE; for (item = instructions; item->key; item++) { if (!strcasecmp(header->name, item->key)) { found = SWITCH_TRUE; break; } } if (!found) { /* Tell the user */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Configuration parameter [%s] is unfortunately not valid, you might want to double-check that.\n", header->name); } } } return SWITCH_STATUS_SUCCESS; }
static switch_event_t *chatplan_hunt(switch_event_t *event) { switch_event_t *extension = NULL; switch_xml_t alt_root = NULL, cfg, xml = NULL, xcontext, xexten = NULL; const char *alt_path; const char *context; const char *from; const char *to; if (!(context = switch_event_get_header(event, "context"))) { context = "default"; } if (!(from = switch_event_get_header(event, "from_user"))) { from = switch_event_get_header(event, "from"); } if (!(to = switch_event_get_header(event, "to_user"))) { to = switch_event_get_header(event, "to"); } alt_path = switch_event_get_header(event, "alt_path"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Processing text message %s->%s in context %s\n", from, to, context); /* get our handle to the "chatplan" section of the config */ if (!zstr(alt_path)) { switch_xml_t conf = NULL, tag = NULL; if (!(alt_root = switch_xml_parse_file_simple(alt_path))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of [%s] failed\n", alt_path); goto done; } if ((conf = switch_xml_find_child(alt_root, "section", "name", "chatplan")) && (tag = switch_xml_find_child(conf, "chatplan", NULL, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Getting chatplan from alternate path: %s\n", alt_path); xml = alt_root; cfg = tag; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of chatplan failed\n"); goto done; } } else { if (switch_xml_locate("chatplan", NULL, NULL, NULL, &xml, &cfg, event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of chatplan failed\n"); goto done; } } /* get a handle to the context tag */ if (!(xcontext = switch_xml_find_child(cfg, "context", "name", context))) { if (!(xcontext = switch_xml_find_child(cfg, "context", "name", "global"))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Context %s not found\n", context); goto done; } } xexten = switch_xml_child(xcontext, "extension"); while (xexten) { int proceed = 0; const char *cont = switch_xml_attr(xexten, "continue"); const char *exten_name = switch_xml_attr(xexten, "name"); if (!exten_name) { exten_name = "UNKNOWN"; } switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Chatplan: %s parsing [%s->%s] continue=%s\n", to, context, exten_name, cont ? cont : "false"); proceed = parse_exten(event, xexten, &extension); if (proceed && !switch_true(cont)) { break; } xexten = xexten->next; } switch_xml_free(xml); xml = NULL; done: switch_xml_free(xml); return extension; }
void do_telecast(switch_stream_handle_t *stream) { char *path_info = switch_event_get_header(stream->param_event, "http-path-info"); char *uuid = strdup(path_info + 4); switch_core_session_t *tsession; char *fname = "stream.mp3"; if ((fname = strchr(uuid, '/'))) { *fname++ = '\0'; } if (!(tsession = switch_core_session_locate(uuid))) { char *ref = switch_event_get_header(stream->param_event, "http-referer"); stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>Not Found!</h2>\n" "<META http-equiv=\"refresh\" content=\"1;URL=%s\">", ref); } else { switch_media_bug_t *bug = NULL; switch_buffer_t *buffer = NULL; switch_mutex_t *mutex; switch_channel_t *channel = switch_core_session_get_channel(tsession); lame_global_flags *gfp = NULL; switch_codec_implementation_t read_impl = { 0 }; switch_core_session_get_read_impl(tsession, &read_impl); if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stepping into media path so this will work!\n"); switch_ivr_media(uuid, SMF_REBRIDGE); } if (!(gfp = lame_init())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n"); goto end; } lame_set_num_channels(gfp, read_impl.number_of_channels); lame_set_in_samplerate(gfp, read_impl.actual_samples_per_second); lame_set_brate(gfp, 16 * (read_impl.actual_samples_per_second / 8000) * read_impl.number_of_channels); lame_set_mode(gfp, 3); lame_set_quality(gfp, 2); lame_set_errorf(gfp, log_error); lame_set_debugf(gfp, log_debug); lame_set_msgf(gfp, log_msg); lame_set_bWriteVbrTag(gfp, 0); lame_mp3_tags_fid(gfp, NULL); lame_init_params(gfp); lame_print_config(gfp); switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession)); switch_buffer_create_dynamic(&buffer, 1024, 2048, 0); switch_buffer_add_mutex(buffer, mutex); if (switch_core_media_bug_add(tsession, "telecast", NULL, telecast_callback, buffer, 0, SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING, &bug) != SWITCH_STATUS_SUCCESS) { goto end; } stream->write_function(stream, "Content-type: audio/mpeg\r\n" "Content-Disposition: inline; filename=\"%s\"\r\n\r\n", fname); while (switch_channel_ready(channel)) { unsigned char mp3buf[TC_BUFFER_SIZE] = ""; int rlen; uint8_t buf[1024]; switch_size_t bytes = 0; if (switch_buffer_inuse(buffer) >= 1024) { switch_buffer_lock(buffer); bytes = switch_buffer_read(buffer, buf, sizeof(buf)); switch_buffer_unlock(buffer); } else { if (!bytes) { switch_cond_next(); continue; } memset(buf, 0, bytes); } if ((rlen = lame_encode_buffer(gfp, (void *) buf, NULL, bytes / 2, mp3buf, sizeof(mp3buf))) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen); goto end; } if (rlen) { if (stream->raw_write_function(stream, mp3buf, rlen)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n"); goto end; } } } end: switch_safe_free(uuid); if (gfp) { lame_close(gfp); gfp = NULL; } if (bug) { switch_core_media_bug_remove(tsession, &bug); } if (buffer) { switch_buffer_destroy(&buffer); } switch_core_session_rwunlock(tsession); } }
static switch_status_t load_config(switch_memory_pool_t *pool) { char *cf = "cdr_csv.conf"; switch_xml_t cfg, xml, settings, param; switch_status_t status = SWITCH_STATUS_SUCCESS; memset(&globals, 0, sizeof(globals)); switch_core_hash_init(&globals.fd_hash, pool); switch_core_hash_init(&globals.template_hash, pool); globals.pool = pool; switch_core_hash_insert(globals.template_hash, "default", default_template); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding default template.\n"); globals.legs = CDR_LEG_A; if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) { if ((settings = switch_xml_child(cfg, "settings"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "debug")) { globals.debug = switch_true(val); } else if (!strcasecmp(var, "legs")) { globals.legs = 0; if (strchr(val, 'a')) { globals.legs |= CDR_LEG_A; } if (strchr(val, 'b')) { globals.legs |= CDR_LEG_B; } } else if (!strcasecmp(var, "log-base")) { globals.log_dir = switch_core_sprintf(pool, "%s%scdr-csv", val, SWITCH_PATH_SEPARATOR); } else if (!strcasecmp(var, "rotate-on-hup")) { globals.rotate = switch_true(val); } else if (!strcasecmp(var, "default-template")) { globals.default_template = switch_core_strdup(pool, val); } else if (!strcasecmp(var, "master-file-only")) { globals.masterfileonly = switch_true(val); } } } if ((settings = switch_xml_child(cfg, "templates"))) { for (param = switch_xml_child(settings, "template"); param; param = param->next) { char *var = (char *) switch_xml_attr(param, "name"); if (var) { char *tpl; size_t len = strlen(param->txt) + 2; if (end_of(param->txt) != '\n') { tpl = switch_core_alloc(pool, len); switch_snprintf(tpl, len, "%s\n", param->txt); } else { tpl = switch_core_strdup(pool, param->txt); } switch_core_hash_insert(globals.template_hash, var, tpl); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding template %s.\n", var); } } } switch_xml_free(xml); } if (zstr(globals.default_template)) { globals.default_template = switch_core_strdup(pool, "default"); } if (!globals.log_dir) { globals.log_dir = switch_core_sprintf(pool, "%s%scdr-csv", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); } return status; }