From 83f69a41e8320273e2e44dc7711002b62b36c240 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 24 May 2014 22:29:06 +0000 Subject: [PATCH 01/47] Add in-code documentation for mod_fifo The goal here is to describe theory. We want to illuminate what the code is trying to do and what the core concepts are. --- src/mod/applications/mod_fifo/mod_fifo.c | 64 ++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 3e70790315..b77b2adc14 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -24,6 +24,7 @@ * Contributor(s): * * Anthony Minessale II + * Travis Cross * * mod_fifo.c -- FIFO * @@ -35,6 +36,69 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown); SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load); SWITCH_MODULE_DEFINITION(mod_fifo, mod_fifo_load, mod_fifo_shutdown, NULL); +/*!\file + * # Theory of operation + * + * ## Kinds of things + * + * The fifo systems deals in various kinds of things: /fifos nodes/, + * /queues/, /(inbound) callers/, /outbound callers/, /consumers/, and + * /(outbound) members/. + * + * /fifo nodes/ accept callers and work to deliver those callers to + * consumers and members. The nodes contain an array of /queues/ + * indexed by a priority value. + * + * /queues/ contain an array of callers treated as a list. + * + * /callers/ are the channels placed into a fifo node's queue for + * eventual delivery to consumers and members. + * + * /outbound callers/ are persons waiting to be called back via a + * dial string. + * + * /consumers/ are channels for agents who have dialed in to one or + * more fifos and will have callers connected to them. + * + * /members/ are agents who we'll place calls to via a dial string to + * attempt to deliver callers. + * + * An /agent/ may refer to either a /consumer/ or an /member/. + * + * ## Outbound Strategies + * + * An outbound strategy defines the way in which we attempt to deliver + * callers to members. + * + * The default strategy, /ringall/, preserves the caller ID of the + * caller being delivered. Because this means we must choose a caller + * before we place the call to the member, this impacts the order in + * which calls are delivered and the rate at which we can deliver + * those calls. + * + * The /enterprise/ outbound strategy does not preserve the caller ID + * of the caller thereby allowing deliver of callers to agents at the + * fastest possible rate. + * + * ## Manual calls + * + * The fifo system provides a way to prevent members on non-fifo calls + * from receiving a call from the fifo system. We do this by tracking + * non-fifo calls in a special fifo named `manual_calls`. When + * creating a channel for an agent we set the channel variable + * `fifo_outbound_uuid` to an arbitrary unique value for that agent, + * then call `fifo_track_call`. For the corresponding member we must + * also set `{fifo_outbound_uuid=}` to the same value. + * + * ## Importance + * + * Importance is a value 0-9 that can be associated with a fifo. The + * default value is 0. If the fifo is being dynamically created the + * importance of the fifo can be set when calling the `fifo` + * application. If the fifo already exists the importance value + * passed to the fifo application will be ignored. + */ + #define MANUAL_QUEUE_NAME "manual_calls" #define FIFO_EVENT "fifo::info" From 8ccd13bd9aa631bc51dddee2754a74719ff004dd Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 16:10:34 +0000 Subject: [PATCH 02/47] mod_fifo: Document load_config() --- src/mod/applications/mod_fifo/mod_fifo.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index b77b2adc14..c557b3ab97 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4338,6 +4338,20 @@ static void extract_fifo_outbound_uuid(char *string, char *uuid, switch_size_t l switch_event_destroy(&ovars); } +/*! + * Load or reload the configuration + * + * On the initial load, non-static members are preserved unless the + * parameter `delete-all-outbound-members-on-startup` is set. The + * parameter `del_all` is ignored in this case. + * + * On reload, non-static members are preserved unless `del_all` is + * set. + * + * \param reload true if we're reloading the config + * \param del_all delete all outbound members when reloading; + * not used unless reload is true + */ static switch_status_t load_config(int reload, int del_all) { char *cf = "fifo.conf"; From 84d6b2e35144673b5042b44ca933f1b144208a2f Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 24 May 2014 23:03:07 +0000 Subject: [PATCH 03/47] mod_fifo: Consolidate code --- src/mod/applications/mod_fifo/mod_fifo.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index c557b3ab97..70a49dedb7 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4373,11 +4373,8 @@ static switch_status_t load_config(int reload, int del_all) if ((settings = switch_xml_child(cfg, "settings"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { - char *var = NULL; - char *val = NULL; - - var = (char *) switch_xml_attr_soft(param, "name"); - val = (char *) switch_xml_attr_soft(param, "value"); + char *var = (char*)switch_xml_attr_soft(param, "name"); + char *val = (char*)switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "outbound-strategy") && !zstr(val)) { default_strategy = parse_strat(val); From 20f35e4591ad62c36c1cde259d8c7f9c0aa48ebc Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 24 May 2014 23:04:36 +0000 Subject: [PATCH 04/47] mod_fifo: Improve function names --- src/mod/applications/mod_fifo/mod_fifo.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 70a49dedb7..47a1845f78 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -395,7 +395,7 @@ struct callback { }; typedef struct callback callback_t; -static const char *strat_parse(outbound_strategy_t s) +static const char *print_strategy(outbound_strategy_t s) { switch (s) { case NODE_STRATEGY_RINGALL: @@ -409,7 +409,7 @@ static const char *strat_parse(outbound_strategy_t s) return "invalid"; } -static outbound_strategy_t parse_strat(const char *name) +static outbound_strategy_t parse_strategy(const char *name) { if (!strcasecmp(name, "ringall")) { return NODE_STRATEGY_RINGALL; @@ -4045,7 +4045,7 @@ static void list_node(fifo_node_t *node, switch_xml_t x_report, int *off, int ve switch_snprintf(tmp, sizeof(buffer), "%u", node->outbound_priority); switch_xml_set_attr_d(x_fifo, "outbound_priority", tmp); - switch_xml_set_attr_d(x_fifo, "outbound_strategy", strat_parse(node->outbound_strategy)); + switch_xml_set_attr_d(x_fifo, "outbound_strategy", print_strategy(node->outbound_strategy)); cc_off = xml_outbound(x_fifo, node, "outbound", "member", cc_off, verbose); cc_off = xml_caller(x_fifo, node, "callers", "caller", cc_off, verbose); @@ -4091,7 +4091,7 @@ void node_dump(switch_stream_handle_t *stream) " waiting: %d\n" , node->name, node->outbound_name, node->outbound_per_cycle, - node->outbound_priority, strat_parse(node->outbound_strategy), + node->outbound_priority, print_strategy(node->outbound_strategy), node->has_outbound, node->outbound_priority, node->busy, @@ -4377,7 +4377,7 @@ static switch_status_t load_config(int reload, int del_all) char *val = (char*)switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "outbound-strategy") && !zstr(val)) { - default_strategy = parse_strat(val); + default_strategy = parse_strategy(val); } if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) { @@ -4566,7 +4566,7 @@ static switch_status_t load_config(int reload, int del_all) node->default_lag = default_lag; if (outbound_strategy) { - node->outbound_strategy = parse_strat(outbound_strategy); + node->outbound_strategy = parse_strategy(outbound_strategy); node->has_outbound = 1; } From a15058406e89698f1270ef55a5b764c4a4cb2ff3 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 24 May 2014 23:08:55 +0000 Subject: [PATCH 05/47] mod_fifo: Cleanup config parsing --- src/mod/applications/mod_fifo/mod_fifo.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 47a1845f78..71b5c29395 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4378,9 +4378,7 @@ static switch_status_t load_config(int reload, int del_all) if (!strcasecmp(var, "outbound-strategy") && !zstr(val)) { default_strategy = parse_strategy(val); - } - - if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) { + } else if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) { if (switch_odbc_available() || switch_pgsql_available()) { switch_set_string(globals.odbc_dsn, val); } else { From f80e869fe096aa0bb843ada039488300056572b1 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 24 May 2014 23:24:07 +0000 Subject: [PATCH 06/47] mod_fifo: Cleanup whitespace in load_config() --- src/mod/applications/mod_fifo/mod_fifo.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 71b5c29395..fd7576d31a 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4402,7 +4402,6 @@ static switch_status_t load_config(int reload, int del_all) } } - if (!(dbh = fifo_get_db_handle())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n"); goto done; @@ -4418,11 +4417,8 @@ static switch_status_t load_config(int reload, int del_all) globals.post_trans_execute, globals.inner_pre_trans_execute, globals.inner_post_trans_execute); - switch_sql_queue_manager_start(globals.qm); - - switch_cache_db_test_reactive(dbh, "delete from fifo_outbound where static = 1 or taking_calls < 0 or stop_time < 0", "drop table fifo_outbound", outbound_sql); switch_cache_db_test_reactive(dbh, "delete from fifo_bridge", "drop table fifo_bridge", bridge_sql); @@ -4465,7 +4461,6 @@ static switch_status_t load_config(int reload, int del_all) node->is_static = 0; } - if ((fifos = switch_xml_child(cfg, "fifos"))) { for (fifo = switch_xml_child(fifos, "fifo"); fifo; fifo = fifo->next) { const char *name, *outbound_strategy; @@ -4506,14 +4501,11 @@ static switch_status_t load_config(int reload, int del_all) } switch_mutex_unlock(globals.mutex); - switch_assert(node); - switch_mutex_lock(node->mutex); outbound_strategy = switch_xml_attr(fifo, "outbound_strategy"); - if ((val = switch_xml_attr(fifo, "outbound_per_cycle"))) { if ((outbound_per_cycle = atoi(val)) < 0) { outbound_per_cycle = 1; @@ -4523,17 +4515,14 @@ static switch_status_t load_config(int reload, int del_all) if ((val = switch_xml_attr(fifo, "retry_delay"))) { int tmp; - if ((tmp = atoi(val)) < 0) { tmp = 0; } - node->retry_delay = tmp; } if ((val = switch_xml_attr(fifo, "outbound_priority"))) { outbound_priority = atoi(val); - if (outbound_priority < 1 || outbound_priority > 10) { outbound_priority = 5; } @@ -4610,7 +4599,6 @@ static switch_status_t load_config(int reload, int del_all) *p = '\0'; } - sql = switch_mprintf("insert into fifo_outbound " "(uuid, fifo_name, originate_string, simo_count, use_count, timeout, lag, " "next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname, taking_calls, " @@ -4618,7 +4606,6 @@ static switch_status_t load_config(int reload, int del_all) "values ('%q','%q','%q',%d,%d,%d,%d,0,0,1,0,0,'%q',%d,%ld,0)", digest, node->name, member->txt, simo_i, 0, timeout_i, lag_i, globals.hostname, taking_calls_i, (long) switch_epoch_time_now(NULL)); - switch_assert(sql); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); free(name_dup); @@ -4630,7 +4617,6 @@ static switch_status_t load_config(int reload, int del_all) switch_mutex_unlock(node->mutex); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s configured\n", node->name); - } } switch_xml_free(xml); @@ -4639,7 +4625,6 @@ static switch_status_t load_config(int reload, int del_all) if (reload) { fifo_node_t *node; - switch_mutex_lock(globals.mutex); for (node = globals.nodes; node; node = node->next) { if (node->ready == -1) { @@ -4651,8 +4636,6 @@ static switch_status_t load_config(int reload, int del_all) switch_mutex_unlock(globals.mutex); } - - return status; } From 31ae5b46556310da84ce2e2aa91c0670a0621bb2 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 24 May 2014 23:47:31 +0000 Subject: [PATCH 07/47] mod_fifo: Cleanup whitespace --- src/mod/applications/mod_fifo/mod_fifo.c | 114 +++++++++++------------ 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index fd7576d31a..443bd5736e 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1,4 +1,4 @@ -/* +/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * Copyright (C) 2005-2014, Anthony Minessale II * @@ -22,7 +22,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * + * * Anthony Minessale II * Travis Cross * @@ -594,14 +594,14 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session args.buflen = sizeof(buf); args.read_frame_callback = chime_read_frame_callback; args.user_data = user_data; - + status = switch_ivr_play_file(session, NULL, cd->list[cd->index], &args); - + if (match_key(cd->exit_key, *buf)) { cd->abort = 1; return SWITCH_STATUS_BREAK; } - + if (status != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_BREAK; } @@ -664,7 +664,7 @@ static struct { char *pre_trans_execute; char *post_trans_execute; char *inner_pre_trans_execute; - char *inner_post_trans_execute; + char *inner_post_trans_execute; switch_sql_queue_manager_t *qm; int allow_transcoding; } globals; @@ -683,11 +683,11 @@ static int fifo_dec_use_count(const char *outbound_id) } } switch_mutex_unlock(globals.use_mutex); - + return r; } -static int fifo_get_use_count(const char *outbound_id) +static int fifo_get_use_count(const char *outbound_id) { int r = 0, *count; @@ -696,12 +696,12 @@ static int fifo_get_use_count(const char *outbound_id) r = *count; } switch_mutex_unlock(globals.use_mutex); - + return r; } -static int fifo_inc_use_count(const char *outbound_id) +static int fifo_inc_use_count(const char *outbound_id) { int r = 0, *count; @@ -714,11 +714,11 @@ static int fifo_inc_use_count(const char *outbound_id) r = ++(*count); switch_mutex_unlock(globals.use_mutex); - + return r; } -static void fifo_init_use_count(void) +static void fifo_init_use_count(void) { switch_mutex_lock(globals.use_mutex); if (globals.use_hash) { @@ -861,7 +861,7 @@ switch_cache_db_handle_t *fifo_get_db_handle(void) switch_cache_db_handle_t *dbh = NULL; char *dsn; - + if (!zstr(globals.odbc_dsn)) { dsn = globals.odbc_dsn; } else { @@ -871,7 +871,7 @@ switch_cache_db_handle_t *fifo_get_db_handle(void) if (switch_cache_db_get_db_handle_dsn(&dbh, dsn) != SWITCH_STATUS_SUCCESS) { dbh = NULL; } - + return dbh; } @@ -881,7 +881,7 @@ static switch_status_t fifo_execute_sql_queued(char **sqlp, switch_bool_t sql_al char *sql; switch_assert(sqlp && *sqlp); - sql = *sqlp; + sql = *sqlp; if (switch_stristr("insert", sql)) { @@ -976,7 +976,7 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu callback_t cbt = { 0 }; char *sql = NULL; char *domain_name = NULL; - + if (!globals.running) { return NULL; } @@ -1007,12 +1007,12 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu cbt.len = sizeof(outbound_count); sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", name); fifo_execute_sql_callback(mutex, sql, sql2str_callback, &cbt); - node->member_count = atoi(outbound_count); + node->member_count = atoi(outbound_count); if (node->member_count > 0) { node->has_outbound = 1; } else { - node->has_outbound = 0; - } + node->has_outbound = 0; + } switch_safe_free(sql); node->importance = importance; @@ -1097,7 +1097,7 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses if ((outbound_id = switch_channel_get_variable(consumer_channel, "fifo_outbound_uuid"))) { use_count = fifo_get_use_count(outbound_id); } - + ts = switch_micro_time_now(); switch_time_exp_lt(&tm, ts); switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); @@ -1462,7 +1462,7 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void if (use_ent) { stream.write_function(&stream, "{ignore_early_media=true,outbound_redirect_fatal=true,leg_timeout=%d,fifo_outbound_uuid=%s,fifo_name=%s}%s%s", - h->timeout, h->uuid, node->name, + h->timeout, h->uuid, node->name, parsed ? parsed : expanded_originate_string, (i == cbh->rowcount - 1) ? "" : SWITCH_ENT_ORIGINATE_DELIM); } else { stream.write_function(&stream, "[leg_timeout=%d,fifo_outbound_uuid=%s,fifo_name=%s]%s,", @@ -1591,7 +1591,7 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void if (!total) goto end; - if (!globals.allow_transcoding && !switch_true(switch_event_get_header(pop, "variable_fifo_allow_transcoding")) && + if (!globals.allow_transcoding && !switch_true(switch_event_get_header(pop, "variable_fifo_allow_transcoding")) && (codec = switch_event_get_header(pop, "variable_rtp_use_codec_name"))) { const char *rate = switch_event_get_header(pop, "variable_rtp_use_codec_rate"); const char *ptime = switch_event_get_header(pop, "variable_rtp_use_codec_ptime"); @@ -2099,7 +2099,7 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o } } } - + if (++cur_priority > 10) { cur_priority = 1; @@ -2514,7 +2514,7 @@ SWITCH_STANDARD_APP(fifo_function) const char *arg_fifo_name = NULL; const char *arg_inout = NULL; const char *serviced_uuid = NULL; - + if (!globals.running) { return; } @@ -3183,18 +3183,18 @@ SWITCH_STANDARD_APP(fifo_function) if (!(switch_channel_ready(channel))) { const char *app = switch_channel_get_variable(other_channel, "current_application"); const char *arg = switch_channel_get_variable(other_channel, "current_application_data"); - switch_caller_extension_t *extension = NULL; + switch_caller_extension_t *extension = NULL; - switch_channel_set_variable_printf(channel, "last_sent_callee_id_name", "%s (AGENT FAIL)", + switch_channel_set_variable_printf(channel, "last_sent_callee_id_name", "%s (AGENT FAIL)", switch_channel_get_variable(other_channel, "caller_id_name")); switch_channel_set_variable(channel, "last_sent_callee_id_number", switch_channel_get_variable(other_channel, "caller_id_number")); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Customer %s %s [%s] appears to be abandoned by agent %s [%s] " "but is still on the line, redirecting them back to the queue with VIP status.\n", - switch_channel_get_name(other_channel), - switch_channel_get_variable(other_channel, "caller_id_name"), + switch_channel_get_name(other_channel), + switch_channel_get_variable(other_channel, "caller_id_name"), switch_channel_get_variable(other_channel, "caller_id_number"), switch_channel_get_variable(channel, "caller_id_name"), switch_channel_get_variable(channel, "caller_id_number")); @@ -3203,7 +3203,7 @@ SWITCH_STANDARD_APP(fifo_function) send_presence(node); check_cancel(node); - + if (app) { extension = switch_caller_extension_new(other_session, app, arg); switch_caller_extension_add_application(other_session, extension, app, arg); @@ -3232,18 +3232,18 @@ SWITCH_STANDARD_APP(fifo_function) originator_cp = switch_channel_get_caller_profile(channel); originatee_cp = switch_channel_get_caller_profile(other_channel); - + switch_channel_set_originator_caller_profile(other_channel, switch_caller_profile_clone(other_session, originator_cp)); switch_channel_set_originatee_caller_profile(channel, switch_caller_profile_clone(session, originatee_cp)); - - + + originator_cp->callee_id_name = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_name); originator_cp->callee_id_number = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_number); originatee_cp->callee_id_name = switch_core_strdup(originatee_cp->pool, originatee_cp->caller_id_name); originatee_cp->callee_id_number = switch_core_strdup(originatee_cp->pool, originatee_cp->caller_id_number); - + originatee_cp->caller_id_name = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_name); originatee_cp->caller_id_number = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_number); @@ -3327,7 +3327,7 @@ SWITCH_STANDARD_APP(fifo_function) switch_event_fire(&event); } - + add_bridge_call(switch_core_session_get_uuid(other_session)); add_bridge_call(switch_core_session_get_uuid(session)); @@ -3361,7 +3361,7 @@ SWITCH_STANDARD_APP(fifo_function) switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_initiated_bridge", NULL); switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_bridge_role", NULL); } - + if (switch_channel_test_flag(channel, CF_TRANSFER) && switch_channel_up(channel)) { switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_initiated_bridge", NULL); switch_channel_set_variable(switch_core_session_get_channel(other_session), "fifo_bridge_role", NULL); @@ -3404,7 +3404,7 @@ SWITCH_STANDARD_APP(fifo_function) switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Hold-Time-us", "%"SWITCH_TIME_T_FMT, hold_usec); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Hold-Time-ms", "%"SWITCH_TIME_T_FMT, (uint64_t)(hold_usec / 1000)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Hold-Time-s", "%"SWITCH_TIME_T_FMT, (uint64_t)(hold_usec / 1000000)); - + switch_event_fire(&event); } @@ -3419,7 +3419,7 @@ SWITCH_STANDARD_APP(fifo_function) if (outbound_id) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Outbound-ID", outbound_id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Consumer-Use-Count", "%d", fifo_get_use_count(outbound_id)); - } + } switch_event_fire(&event); } if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { @@ -3599,7 +3599,7 @@ SWITCH_STANDARD_APP(fifo_function) continue; } switch_thread_rwlock_unlock(node->rwlock); - + if (node->ready == 1 && do_destroy && node_caller_count(node) == 0 && node->consumer_count == 0) { switch_core_hash_delete(globals.fifo_hash, node->name); node->ready = 0; @@ -4370,7 +4370,7 @@ static switch_status_t load_config(int reload, int del_all) } globals.dbname = "fifo"; - + 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"); @@ -4644,8 +4644,8 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co { char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 }; char *sql, *name_dup, *p; - char outbound_count[80] = ""; - callback_t cbt = { 0 }; + char outbound_count[80] = ""; + callback_t cbt = { 0 }; fifo_node_t *node = NULL; if (!fifo_name) return; @@ -4683,17 +4683,17 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); free(name_dup); - cbt.buf = outbound_count; - cbt.len = sizeof(outbound_count); - sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", fifo_name); - fifo_execute_sql_callback(globals.sql_mutex, sql, sql2str_callback, &cbt); - node->member_count = atoi(outbound_count); - if (node->member_count > 0) { - node->has_outbound = 1; - } else { - node->has_outbound = 0; - } - switch_safe_free(sql); + cbt.buf = outbound_count; + cbt.len = sizeof(outbound_count); + sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", fifo_name); + fifo_execute_sql_callback(globals.sql_mutex, sql, sql2str_callback, &cbt); + node->member_count = atoi(outbound_count); + if (node->member_count > 0) { + node->has_outbound = 1; + } else { + node->has_outbound = 0; + } + switch_safe_free(sql); } static void fifo_member_del(char *fifo_name, char *originate_string) @@ -4728,11 +4728,11 @@ static void fifo_member_del(char *fifo_name, char *originate_string) cbt.len = sizeof(outbound_count); sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", node->name); fifo_execute_sql_callback(globals.sql_mutex, sql, sql2str_callback, &cbt); - node->member_count = atoi(outbound_count); + node->member_count = atoi(outbound_count); if (node->member_count > 0) { - node->has_outbound = 1; + node->has_outbound = 1; } else { - node->has_outbound = 0; + node->has_outbound = 0; } switch_safe_free(sql); } @@ -4920,7 +4920,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown) this_node = node; node = node->next; - + switch_mutex_lock(this_node->update_mutex); switch_mutex_lock(this_node->mutex); for (x = 0; x < MAX_PRI; x++) { From 06d94d2c173b5fc534bfcc9463eecadf82c3179a Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 25 May 2014 13:54:25 +0000 Subject: [PATCH 08/47] mod_fifo: Move straggling vars to global struct --- src/mod/applications/mod_fifo/mod_fifo.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 443bd5736e..1b8c0c8fde 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -111,8 +111,6 @@ typedef enum { NODE_STRATEGY_ENTERPRISE } outbound_strategy_t; -static outbound_strategy_t default_strategy = NODE_STRATEGY_RINGALL; - static int marker = 1; typedef struct { @@ -667,6 +665,8 @@ static struct { char *inner_post_trans_execute; switch_sql_queue_manager_t *qm; int allow_transcoding; + switch_bool_t delete_all_members_on_startup; + outbound_strategy_t default_strategy; } globals; @@ -986,7 +986,7 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu node = switch_core_alloc(pool, sizeof(*node)); node->pool = pool; - node->outbound_strategy = default_strategy; + node->outbound_strategy = globals.default_strategy; node->name = switch_core_strdup(node->pool, name); if (!strchr(name, '@')) { @@ -4358,7 +4358,6 @@ static switch_status_t load_config(int reload, int del_all) switch_xml_t cfg, xml, fifo, fifos, member, settings, param; switch_status_t status = SWITCH_STATUS_SUCCESS; char *sql; - switch_bool_t delete_all_outbound_member_on_startup = SWITCH_FALSE; switch_cache_db_handle_t *dbh = NULL; fifo_node_t *node; @@ -4370,14 +4369,15 @@ static switch_status_t load_config(int reload, int del_all) } globals.dbname = "fifo"; - + globals.default_strategy = NODE_STRATEGY_RINGALL; + globals.delete_all_members_on_startup = SWITCH_FALSE; 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, "outbound-strategy") && !zstr(val)) { - default_strategy = parse_strategy(val); + globals.default_strategy = parse_strategy(val); } else if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) { if (switch_odbc_available() || switch_pgsql_available()) { switch_set_string(globals.odbc_dsn, val); @@ -4397,7 +4397,7 @@ static switch_status_t load_config(int reload, int del_all) } else if (!strcasecmp(var, "db-inner-post-trans-execute") && !zstr(val)) { globals.inner_post_trans_execute = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "delete-all-outbound-member-on-startup")) { - delete_all_outbound_member_on_startup = switch_true(val); + globals.delete_all_members_on_startup = switch_true(val); } } } @@ -4447,7 +4447,7 @@ static switch_status_t load_config(int reload, int del_all) switch_mutex_unlock(globals.mutex); } - if ((reload && del_all) || (!reload && delete_all_outbound_member_on_startup)) { + if ((reload && del_all) || (!reload && globals.delete_all_members_on_startup)) { sql = switch_mprintf("delete from fifo_outbound where hostname='%q'", globals.hostname); } else { sql = switch_mprintf("delete from fifo_outbound where static=1 and hostname='%q'", globals.hostname); From a3a62d2481c2fc06c9c91a8051c2a260f8e52e19 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 25 May 2014 14:27:01 +0000 Subject: [PATCH 09/47] mod_fifo: Convert macro to fn and improve name --- src/mod/applications/mod_fifo/mod_fifo.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 1b8c0c8fde..251f596180 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -508,7 +508,9 @@ static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input, return SWITCH_STATUS_SUCCESS; } -#define check_string(s) if (!zstr(s) && !strcasecmp(s, "undef")) { s = NULL; } +static inline void cleanup_fifo_arg(const char **s) { + if (!zstr(*s) && !strcasecmp(*s, "undef")) *s = NULL; +} static int node_caller_count(fifo_node_t *node) { @@ -2607,8 +2609,8 @@ SWITCH_STANDARD_APP(fifo_function) moh = NULL; } - check_string(announce); - check_string(moh); + cleanup_fifo_arg(&announce); + cleanup_fifo_arg(&moh); switch_assert(node); switch_core_media_bug_pause(session); From c6e90e01112e2b7d5c1ae5ac6ae383ad93488aa0 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 25 May 2014 14:46:19 +0000 Subject: [PATCH 10/47] mod_fifo: Refactor out config file reading --- src/mod/applications/mod_fifo/mod_fifo.c | 67 +++++++++++++----------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 251f596180..8a87e2d473 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4340,40 +4340,16 @@ static void extract_fifo_outbound_uuid(char *string, char *uuid, switch_size_t l switch_event_destroy(&ovars); } -/*! - * Load or reload the configuration - * - * On the initial load, non-static members are preserved unless the - * parameter `delete-all-outbound-members-on-startup` is set. The - * parameter `del_all` is ignored in this case. - * - * On reload, non-static members are preserved unless `del_all` is - * set. - * - * \param reload true if we're reloading the config - * \param del_all delete all outbound members when reloading; - * not used unless reload is true - */ -static switch_status_t load_config(int reload, int del_all) -{ - char *cf = "fifo.conf"; - switch_xml_t cfg, xml, fifo, fifos, member, settings, param; - switch_status_t status = SWITCH_STATUS_SUCCESS; - char *sql; - switch_cache_db_handle_t *dbh = NULL; - fifo_node_t *node; +static switch_status_t read_config_file(switch_xml_t *xml, switch_xml_t *cfg) { + const char *cf = "fifo.conf"; + switch_xml_t settings; - strncpy(globals.hostname, switch_core_get_switchname(), sizeof(globals.hostname) - 1); - - if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { + 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; } - - globals.dbname = "fifo"; - globals.default_strategy = NODE_STRATEGY_RINGALL; - globals.delete_all_members_on_startup = SWITCH_FALSE; - if ((settings = switch_xml_child(cfg, "settings"))) { + if ((settings = switch_xml_child(*cfg, "settings"))) { + switch_xml_t param; 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"); @@ -4403,6 +4379,37 @@ static switch_status_t load_config(int reload, int del_all) } } } + return SWITCH_STATUS_SUCCESS; +} + +/*! + * Load or reload the configuration + * + * On the initial load, non-static members are preserved unless the + * parameter `delete-all-outbound-members-on-startup` is set. The + * parameter `del_all` is ignored in this case. + * + * On reload, non-static members are preserved unless `del_all` is + * set. + * + * \param reload true if we're reloading the config + * \param del_all delete all outbound members when reloading; + * not used unless reload is true + */ +static switch_status_t load_config(int reload, int del_all) +{ + switch_xml_t xml, cfg, fifo, fifos, member; + switch_status_t status = SWITCH_STATUS_SUCCESS; + char *sql; + switch_cache_db_handle_t *dbh = NULL; + fifo_node_t *node; + + strncpy(globals.hostname, switch_core_get_switchname(), sizeof(globals.hostname) - 1); + globals.dbname = "fifo"; + globals.default_strategy = NODE_STRATEGY_RINGALL; + globals.delete_all_members_on_startup = SWITCH_FALSE; + + if ((status = read_config_file(&xml, &cfg)) != SWITCH_STATUS_SUCCESS) return status; if (!(dbh = fifo_get_db_handle())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n"); From 2068b284ccd9d6312e75a571d85aefc3305788d6 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 25 May 2014 14:48:47 +0000 Subject: [PATCH 11/47] mod_fifo: Fix memory leak of xml structure If getting the DB handle failed during the load or reload of the configuration, we would leak the XML structure we just allocated for the configuration. --- src/mod/applications/mod_fifo/mod_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 8a87e2d473..de82ff0575 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4628,10 +4628,10 @@ static switch_status_t load_config(int reload, int del_all) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s configured\n", node->name); } } - switch_xml_free(xml); done: + switch_xml_free(xml); if (reload) { fifo_node_t *node; switch_mutex_lock(globals.mutex); From 0526e00457a06644b8298b43281cc34c28d247b9 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 25 May 2014 15:48:17 +0000 Subject: [PATCH 12/47] mod_fifo: Replace global var with local static This marker value is only used in one place. --- src/mod/applications/mod_fifo/mod_fifo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index de82ff0575..a8fcd88c41 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -111,8 +111,6 @@ typedef enum { NODE_STRATEGY_ENTERPRISE } outbound_strategy_t; -static int marker = 1; - typedef struct { int nelm; int idx; @@ -796,6 +794,7 @@ static int check_bridge_call(const char *key) static void add_bridge_call(const char *key) { + static int marker = 1; if (!key) return; switch_mutex_lock(globals.bridge_mutex); From 1f7589d6fa7a152442a24e119190350b93943196 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 25 May 2014 15:57:39 +0000 Subject: [PATCH 13/47] mod_fifo: Refactor --- src/mod/applications/mod_fifo/mod_fifo.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index a8fcd88c41..6d9f8da59d 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4481,9 +4481,7 @@ static switch_status_t load_config(int reload, int del_all) int ring_timeout = 60; int default_lag = 30; - name = switch_xml_attr(fifo, "name"); - - if (!name) { + if (!(name = switch_xml_attr(fifo, "name"))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fifo has no name!\n"); continue; } From 17070e9dac68d2a0912e7cb7112c723db2c986fd Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 25 May 2014 16:07:35 +0000 Subject: [PATCH 14/47] mod_fifo: Improve strategy thread function names --- src/mod/applications/mod_fifo/mod_fifo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 6d9f8da59d..a5e24c6388 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1342,7 +1342,7 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ } -static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void *obj) +static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thread, void *obj) { struct callback_helper *cbh = (struct callback_helper *) obj; char *node_name; @@ -1744,7 +1744,7 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void return NULL; } -static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj) +static void *SWITCH_THREAD_FUNC outbound_enterprise_thread_run(switch_thread_t *thread, void *obj) { struct call_helper *h = (struct call_helper *) obj; @@ -1946,7 +1946,7 @@ static int place_call_enterprise_callback(void *pArg, int argc, char **argv, cha switch_threadattr_create(&thd_attr, h->pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&thread, thd_attr, o_thread_run, h, h->pool); + switch_thread_create(&thread, thd_attr, outbound_enterprise_thread_run, h, h->pool); (*need)--; @@ -2003,7 +2003,7 @@ static void find_consumers(fifo_node_t *node) switch_threadattr_create(&thd_attr, cbh->pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&thread, thd_attr, ringall_thread_run, cbh, cbh->pool); + switch_thread_create(&thread, thd_attr, outbound_ringall_thread_run, cbh, cbh->pool); } else { switch_core_destroy_memory_pool(&pool); } From 353c3b19fae384797d04ae0f793df4034d2b8112 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 25 May 2014 16:46:44 +0000 Subject: [PATCH 15/47] mod_fifo: Document fifo_node::outbound_name --- src/mod/applications/mod_fifo/mod_fifo.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index a5e24c6388..949717d93c 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -348,6 +348,19 @@ static switch_status_t fifo_queue_popfly(fifo_queue_t *queue, const char *uuid) +/*! + * \struct fifo_node + * + * \var fifo_node::outbound_name + * \brief Name of fifo in caller ID + * + * For the ringall strategy, this value is a prefix for the + * caller ID shown to agents. If the value starts with '=' then the + * actual caller ID is replaced completely. + * + * For the enterprise strategy, this value is used instead of the + * queue name in the caller ID. + */ struct fifo_node { char *name; switch_mutex_t *mutex; From 6105e9783c98499c939c47c39ff596cda768bf8b Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 05:17:19 +0000 Subject: [PATCH 16/47] mod_fifo: Refactor load_config() Reduce number of local variables where possible; consolidate lines. --- src/mod/applications/mod_fifo/mod_fifo.c | 95 +++++++++--------------- 1 file changed, 36 insertions(+), 59 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 949717d93c..2bc691eb0e 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4484,15 +4484,9 @@ static switch_status_t load_config(int reload, int del_all) if ((fifos = switch_xml_child(cfg, "fifos"))) { for (fifo = switch_xml_child(fifos, "fifo"); fifo; fifo = fifo->next) { - const char *name, *outbound_strategy; + const char *name, *sp; const char *val; - int imp = 0, outbound_per_cycle = 1, outbound_priority = 5; - int simo_i = 1; - int taking_calls_i = 1; - int timeout_i = 60; - int lag_i = 10; - int ring_timeout = 60; - int default_lag = 30; + int i, importance = 0; if (!(name = switch_xml_attr(fifo, "name"))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fifo has no name!\n"); @@ -4504,15 +4498,13 @@ static switch_status_t load_config(int reload, int del_all) continue; } - if ((val = switch_xml_attr(fifo, "importance"))) { - if ((imp = atoi(val)) < 0) { - imp = 0; - } + if ((val = switch_xml_attr(fifo, "importance")) && !(i = atoi(val)) < 0) { + importance = i; } switch_mutex_lock(globals.mutex); if (!(node = switch_core_hash_find(globals.fifo_hash, name))) { - node = create_node(name, imp, globals.sql_mutex); + node = create_node(name, importance, globals.sql_mutex); } if ((val = switch_xml_attr(fifo, "outbound_name"))) { @@ -4523,64 +4515,54 @@ static switch_status_t load_config(int reload, int del_all) switch_assert(node); switch_mutex_lock(node->mutex); - outbound_strategy = switch_xml_attr(fifo, "outbound_strategy"); + if ((sp = switch_xml_attr(fifo, "outbound_strategy"))) { + node->outbound_strategy = parse_strategy(sp); + node->has_outbound = 1; + } + node->outbound_per_cycle = 1; if ((val = switch_xml_attr(fifo, "outbound_per_cycle"))) { - if ((outbound_per_cycle = atoi(val)) < 0) { - outbound_per_cycle = 1; + if (!(i = atoi(val)) < 0) { + node->outbound_per_cycle = i; } node->has_outbound = 1; } if ((val = switch_xml_attr(fifo, "retry_delay"))) { - int tmp; - if ((tmp = atoi(val)) < 0) { - tmp = 0; - } - node->retry_delay = tmp; + if ((i = atoi(val)) < 0) i = 0; + node->retry_delay = i; } + node->outbound_priority = 5; if ((val = switch_xml_attr(fifo, "outbound_priority"))) { - outbound_priority = atoi(val); - if (outbound_priority < 1 || outbound_priority > 10) { - outbound_priority = 5; + i = atoi(val); + if (!(i < 1 || i > 10)) { + node->outbound_priority = i; } node->has_outbound = 1; } + node->ring_timeout = 60; if ((val = switch_xml_attr(fifo, "outbound_ring_timeout"))) { - int tmp = atoi(val); - if (tmp > 10) { - ring_timeout = tmp; + if ((i = atoi(val)) > 10) { + node->ring_timeout = i; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid ring_timeout: must be > 10 for queue %s\n", node->name); } } + node->default_lag = 30; if ((val = switch_xml_attr(fifo, "outbound_default_lag"))) { - int tmp = atoi(val); - if (tmp > 10) { - default_lag = tmp; + if ((i = atoi(val)) > 10) { + node->default_lag = i; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid default_lag: must be > 10 for queue %s\n", node->name); } } - node->ring_timeout = ring_timeout; - node->outbound_per_cycle = outbound_per_cycle; - node->outbound_priority = outbound_priority; - node->default_lag = default_lag; - - if (outbound_strategy) { - node->outbound_strategy = parse_strategy(outbound_strategy); - node->has_outbound = 1; - } - for (member = switch_xml_child(fifo, "member"); member; member = member->next) { - const char *simo = switch_xml_attr_soft(member, "simo"); - const char *lag = switch_xml_attr_soft(member, "lag"); - const char *timeout = switch_xml_attr_soft(member, "timeout"); - const char *taking_calls = switch_xml_attr_soft(member, "taking_calls"); + const char *simo, *taking_calls, *timeout, *lag; + int simo_i = 1, taking_calls_i = 1, timeout_i = 60, lag_i = 10; char *name_dup, *p; char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 }; @@ -4590,27 +4572,23 @@ static switch_status_t load_config(int reload, int del_all) switch_md5_string(digest, (void *) member->txt, strlen(member->txt)); } - if (simo) { + if ((simo = switch_xml_attr_soft(member, "simo"))) { simo_i = atoi(simo); } - if (taking_calls) { - if ((taking_calls_i = atoi(taking_calls)) < 1) { - taking_calls_i = 1; - } + if ((taking_calls = switch_xml_attr_soft(member, "taking_calls")) + && (taking_calls_i = atoi(taking_calls)) < 1) { + taking_calls_i = 1; } - if (timeout) { - if ((timeout_i = atoi(timeout)) < 10) { - timeout_i = ring_timeout; - } - + if ((timeout = switch_xml_attr_soft(member, "timeout")) + && (timeout_i = atoi(timeout)) < 10) { + timeout_i = node->ring_timeout; } - if (lag) { - if ((lag_i = atoi(lag)) < 0) { - lag_i = default_lag; - } + if ((lag = switch_xml_attr_soft(member, "lag")) + && (lag_i = atoi(lag)) < 0) { + lag_i = node->default_lag; } name_dup = strdup(node->name); @@ -4634,7 +4612,6 @@ static switch_status_t load_config(int reload, int del_all) node->ready = 1; node->is_static = 1; switch_mutex_unlock(node->mutex); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s configured\n", node->name); } } From 628b6c19ab7a9d4c2b91bc49ba0be53b08261263 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 05:24:14 +0000 Subject: [PATCH 17/47] mod_fifo: Remove dead code We were making a copy of the fifo name and stripping any domain name, but then not using the value. --- src/mod/applications/mod_fifo/mod_fifo.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 2bc691eb0e..d2b8a4a520 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4563,7 +4563,6 @@ static switch_status_t load_config(int reload, int del_all) for (member = switch_xml_child(fifo, "member"); member; member = member->next) { const char *simo, *taking_calls, *timeout, *lag; int simo_i = 1, taking_calls_i = 1, timeout_i = 60, lag_i = 10; - char *name_dup, *p; char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 }; if (switch_stristr("fifo_outbound_uuid=", member->txt)) { @@ -4591,11 +4590,6 @@ static switch_status_t load_config(int reload, int del_all) lag_i = node->default_lag; } - name_dup = strdup(node->name); - if ((p = strchr(name_dup, '@'))) { - *p = '\0'; - } - sql = switch_mprintf("insert into fifo_outbound " "(uuid, fifo_name, originate_string, simo_count, use_count, timeout, lag, " "next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname, taking_calls, " @@ -4605,7 +4599,6 @@ static switch_status_t load_config(int reload, int del_all) (long) switch_epoch_time_now(NULL)); switch_assert(sql); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); - free(name_dup); node->has_outbound = 1; node->member_count++; } From e677da587044dfdea2cddf2b3edcb7f0d18cc247 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 05:33:02 +0000 Subject: [PATCH 18/47] mod_fifo: Refactor in create_node() --- src/mod/applications/mod_fifo/mod_fifo.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index d2b8a4a520..d684773b19 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -995,7 +995,6 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu return NULL; } - switch_core_new_memory_pool(&pool); node = switch_core_alloc(pool, sizeof(*node)); @@ -1022,11 +1021,7 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", name); fifo_execute_sql_callback(mutex, sql, sql2str_callback, &cbt); node->member_count = atoi(outbound_count); - if (node->member_count > 0) { - node->has_outbound = 1; - } else { - node->has_outbound = 0; - } + node->has_outbound = (node->member_count > 0) ? 1 : 0; switch_safe_free(sql); node->importance = importance; From e241477860fabc7424d3a4c3a2c60c4573ea193a Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 14:42:06 +0000 Subject: [PATCH 19/47] mod_fifo: Tighten up some whitespace --- src/mod/applications/mod_fifo/mod_fifo.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index d684773b19..d60cc71e26 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -166,37 +166,26 @@ static void change_pos(switch_event_t *event, int pos) char tmp[30] = ""; if (zstr(uuid)) return; - if (!(session = switch_core_session_locate(uuid))) { return; } - channel = switch_core_session_get_channel(session); - switch_snprintf(tmp, sizeof(tmp), "%d", pos); switch_channel_set_variable(channel, "fifo_position", tmp); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fifo_position", tmp); - switch_core_session_rwunlock(session); - - } static switch_status_t fifo_queue_push(fifo_queue_t *queue, switch_event_t *ptr) { switch_mutex_lock(queue->mutex); - if (queue->idx == queue->nelm) { switch_mutex_unlock(queue->mutex); return SWITCH_STATUS_FALSE; } - queue->data[queue->idx++] = ptr; - switch_mutex_unlock(queue->mutex); - return SWITCH_STATUS_SUCCESS; - } static int fifo_queue_size(fifo_queue_t *queue) @@ -205,7 +194,6 @@ static int fifo_queue_size(fifo_queue_t *queue) switch_mutex_lock(queue->mutex); s = queue->idx; switch_mutex_unlock(queue->mutex); - return s; } @@ -248,9 +236,7 @@ static switch_status_t fifo_queue_pop(fifo_queue_t *queue, switch_event_t **pop, } switch_mutex_unlock(queue->mutex); - return SWITCH_STATUS_SUCCESS; - } From 1eaf4b50caae97ebc4d8aa25e3ad9e6363f70f93 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 14:42:20 +0000 Subject: [PATCH 20/47] mod_fifo: Document remove parameter of fifo_queue_pop() --- src/mod/applications/mod_fifo/mod_fifo.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index d60cc71e26..1cf1d0cf9e 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -197,6 +197,12 @@ static int fifo_queue_size(fifo_queue_t *queue) return s; } +/*! + * \param remove Whether to remove the popped event from the queue + * If remove is 0, do not remove the popped event. If it is 1, remove + * it if it is not an event for an outbound caller. If it is 2, + * always remove it. + */ static switch_status_t fifo_queue_pop(fifo_queue_t *queue, switch_event_t **pop, int remove) { int i, j; From b914c2374dbff745c814559f78e9cab85dd1d93d Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 14:52:04 +0000 Subject: [PATCH 21/47] mod_fifo: Document fifo_queue_pop_nameval() --- src/mod/applications/mod_fifo/mod_fifo.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 1cf1d0cf9e..ba05976f2e 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -245,7 +245,16 @@ static switch_status_t fifo_queue_pop(fifo_queue_t *queue, switch_event_t **pop, return SWITCH_STATUS_SUCCESS; } - +/*! \brief Remove matching event from queue + * + * Each event in the queue will be checked to see whether it has a + * header equal to name whose value is equal to val. If it does, that + * event will be returned unless the event is for an outbound caller. + * If name starts with '+' or remove == 2 then forcing is enabled and + * the event will be returned in any case. If remove > 0 then the + * returned event will be removed from the queue and the remaining + * elements shifted to make them contiguous. + */ static switch_status_t fifo_queue_pop_nameval(fifo_queue_t *queue, const char *name, const char *val, switch_event_t **pop, int remove) { int i, j, force = 0; From 077579b131d7d8c0fcc3540a39f003943b999f09 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 15:01:06 +0000 Subject: [PATCH 22/47] mod_fifo: Document fifo_queue_popfly() --- src/mod/applications/mod_fifo/mod_fifo.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index ba05976f2e..4621f29be1 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -309,6 +309,12 @@ static switch_status_t fifo_queue_pop_nameval(fifo_queue_t *queue, const char *n return SWITCH_STATUS_SUCCESS; } +/*! \brief Destroy event with given uuid and remove it from queue + * + * Elements of the queue are searched until a matching uuid is found. + * That uuid is then destroyed and removed from the queue. The + * remaining elements are shifted to make them contiguous. + */ static switch_status_t fifo_queue_popfly(fifo_queue_t *queue, const char *uuid) { int i, j; From c34ad2c0eceeb44253cc87067dbc8d8d3563cec3 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 15:09:20 +0000 Subject: [PATCH 23/47] mod_fifo: Avoid getting a var when we won't use it --- src/mod/applications/mod_fifo/mod_fifo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 4621f29be1..fdd68441d3 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -468,9 +468,8 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit switch_channel_t *bchan = switch_core_session_get_channel(bleg); switch_channel_t *channel = switch_core_session_get_channel(session); - const char *consumer_exit_key = switch_channel_get_variable(channel, "fifo_consumer_exit_key"); - if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_BRIDGE_ORIGINATOR)) { + const char *consumer_exit_key = switch_channel_get_variable(channel, "fifo_consumer_exit_key"); if (consumer_exit_key && dtmf->digit == *consumer_exit_key) { switch_channel_hangup(bchan, SWITCH_CAUSE_NORMAL_CLEARING); return SWITCH_STATUS_BREAK; From 7920630c8f5b3ad55bf867093ffb53cc6ec41cb6 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 15:20:38 +0000 Subject: [PATCH 24/47] mod_fifo: Refactor DTMF exit key matching --- src/mod/applications/mod_fifo/mod_fifo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index fdd68441d3..8f78c85711 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -470,10 +470,8 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_BRIDGE_ORIGINATOR)) { const char *consumer_exit_key = switch_channel_get_variable(channel, "fifo_consumer_exit_key"); - if (consumer_exit_key && dtmf->digit == *consumer_exit_key) { - switch_channel_hangup(bchan, SWITCH_CAUSE_NORMAL_CLEARING); - return SWITCH_STATUS_BREAK; - } else if (!consumer_exit_key && dtmf->digit == '*') { + if (!consumer_exit_key) consumer_exit_key = "*"; + if (dtmf->digit == *consumer_exit_key) { switch_channel_hangup(bchan, SWITCH_CAUSE_NORMAL_CLEARING); return SWITCH_STATUS_BREAK; } else if (dtmf->digit == '0') { From 27b3ddcc9f3dc7c92ef26f754d9aa630d61e97fb Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 16:02:17 +0000 Subject: [PATCH 25/47] mod_fifo: Document the consumer DTMF callback --- src/mod/applications/mod_fifo/mod_fifo.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 8f78c85711..31bcbec9bc 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -457,6 +457,19 @@ static switch_bool_t match_key(const char *caller_exit_key, char key) return SWITCH_FALSE; } +/*! \brief Handler for consumer DTMF + * + * When `fifo_consumer_exit_key` is pressed by the consumer we hangup + * on the caller (unless we've put the caller on hold). The default + * exit key is '*'. + * + * When the consumer presses '0' we put both legs on hold and play + * hold music as follows. To the caller we play `fifo_music` or the + * default hold music for the channel. To the consumer we play + * `fifo_hold_music`, or `fifo_music`, or the default hold music for + * the channel. The consumer can press '0' again to pick up the + * caller from hold. + */ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) { switch_core_session_t *bleg = (switch_core_session_t *) buf; From 3e6199eace5903a952ae993b3797fe612d1db6c1 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 16:19:34 +0000 Subject: [PATCH 26/47] mod_fifo: Remove reimplementation of strchr() --- src/mod/applications/mod_fifo/mod_fifo.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 31bcbec9bc..d6a2159897 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -447,16 +447,6 @@ static int sql2str_callback(void *pArg, int argc, char **argv, char **columnName return 0; } -static switch_bool_t match_key(const char *caller_exit_key, char key) -{ - while (caller_exit_key && *caller_exit_key) { - if (*caller_exit_key++ == key) { - return SWITCH_TRUE; - } - } - return SWITCH_FALSE; -} - /*! \brief Handler for consumer DTMF * * When `fifo_consumer_exit_key` is pressed by the consumer we hangup @@ -522,7 +512,7 @@ static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input, switch_channel_t *channel = switch_core_session_get_channel(session); const char *caller_exit_key = switch_channel_get_variable(channel, "fifo_caller_exit_key"); - if (match_key(caller_exit_key, dtmf->digit)) { + if (caller_exit_key && dtmf->digit && strchr(caller_exit_key, dtmf->digit)) { char *bp = buf; *bp = dtmf->digit; return SWITCH_STATUS_BREAK; @@ -625,7 +615,7 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session status = switch_ivr_play_file(session, NULL, cd->list[cd->index], &args); - if (match_key(cd->exit_key, *buf)) { + if (cd->exit_key && *buf && strchr(cd->exit_key, *buf)) { cd->abort = 1; return SWITCH_STATUS_BREAK; } @@ -2781,7 +2771,7 @@ SWITCH_STANDARD_APP(fifo_function) goto abort; } - if (match_key(caller_exit_key, *buf)) { + if (caller_exit_key && *buf && strchr(caller_exit_key, *buf)) { switch_channel_set_variable(channel, "fifo_caller_exit_key", (char *)buf); aborted = 1; goto abort; From 2c7c15261d672b46b5526dd7a30ec7511689d9bd Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 17:34:22 +0000 Subject: [PATCH 27/47] mod_fifo: Document caller DTMF handler --- src/mod/applications/mod_fifo/mod_fifo.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index d6a2159897..8db7a5c545 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -503,6 +503,13 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit return SWITCH_STATUS_SUCCESS; } +/*! \brief Handler for caller DTMF + * + * The channel variable `fifo_caller_exit_key` can be set to one or + * more digits that when pressed will cause the caller to exit from + * the fifo. We'll return via a single character in `buf` the digit + * that was pressed (not null-terminated). + */ static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) { switch (itype) { From 5f4ed9c123593263f4f6d3de033e156d319289f1 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 17:50:43 +0000 Subject: [PATCH 28/47] mod_fifo: Document fifo_chime_data::list --- src/mod/applications/mod_fifo/mod_fifo.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 8db7a5c545..911cd1fa4d 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -565,6 +565,12 @@ static void node_remove_uuid(fifo_node_t *node, const char *uuid) return; } +/*!\struct fifo_chime_data + * + * \var fifo_chime_data::list + * A list of strings representing things to play back to the caller + * while they are waiting to be connected with an agent. + */ #define MAX_CHIME 25 struct fifo_chime_data { char *list[MAX_CHIME]; From 42ebfbfc5980baa35fbf9c1e4704201ec8dfcb8f Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 18:00:02 +0000 Subject: [PATCH 29/47] mod_fifo: Document the fifo_queue_t structure --- src/mod/applications/mod_fifo/mod_fifo.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 911cd1fa4d..42f030d3c5 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -111,6 +111,16 @@ typedef enum { NODE_STRATEGY_ENTERPRISE } outbound_strategy_t; +/*!\struct fifo_queue_t + * \brief Queue of callers + * + * Callers are placed into a queue as events in `data` which is an + * array of such events. The array size is hard-coded as 1000 + * elements. + * + * Fifo nodes are composed of an array of these queues representing + * each priority level of the fifo. + */ typedef struct { int nelm; int idx; From edecd151a51ad292ffa0f9d3b2f34593d3d4afc3 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 18:21:45 +0000 Subject: [PATCH 30/47] mod_fifo: Document the read_frame_callbacks --- src/mod/applications/mod_fifo/mod_fifo.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 42f030d3c5..09da73cd21 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -599,6 +599,11 @@ struct fifo_chime_data { typedef struct fifo_chime_data fifo_chime_data_t; +/*! \brief Enforce the `fifo_orbit_timeout` + * + * If the caller has been waiting longer than the `fifo_orbit_timeout` + * we break out so the orbit can do something else with the call. + */ static switch_status_t chime_read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data) { fifo_chime_data_t *cd = (fifo_chime_data_t *) user_data; @@ -611,7 +616,11 @@ static switch_status_t chime_read_frame_callback(switch_core_session_t *session, return SWITCH_STATUS_SUCCESS; } - +/*! \brief Handle chimes and timeouts for callers + * + * Play back the chimes in order spaced out by the given `freq` while + * ensuring that we don't exceed the `orbit_timeout`. + */ static switch_status_t caller_read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data) { fifo_chime_data_t *cd = (fifo_chime_data_t *) user_data; @@ -655,6 +664,13 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session return chime_read_frame_callback(session, frame, user_data); } +/*! \brief Handler for waiting consumers + * + * In `user_data` we'll be passed an array of fifo_nodes representing + * the fifos for which this consumer will accept calls. If any of + * those fifos have a caller in them, we break out so we can accept + * the call. + */ static switch_status_t consumer_read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data) { fifo_node_t *node, **node_list = (fifo_node_t **) user_data; From 597a5c1208991c072a949c644d58dcf819da6315 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 18:34:50 +0000 Subject: [PATCH 31/47] mod_fifo: Remove empty declaration --- src/mod/applications/mod_fifo/mod_fifo.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 09da73cd21..935431c20d 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -692,8 +692,6 @@ static switch_status_t consumer_read_frame_callback(switch_core_session_t *sessi return SWITCH_STATUS_SUCCESS; } -struct fifo_node; - static struct { switch_hash_t *caller_orig_hash; switch_hash_t *consumer_orig_hash; From a5f982fd1c9019db11853d18736fc343245fb3f2 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 18:43:23 +0000 Subject: [PATCH 32/47] mod_fifo: Replace duplicate code with node_caller_count() --- src/mod/applications/mod_fifo/mod_fifo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 935431c20d..c1a8b27f74 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -674,15 +674,13 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session static switch_status_t consumer_read_frame_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data) { fifo_node_t *node, **node_list = (fifo_node_t **) user_data; - int x = 0, total = 0, i = 0; + int total = 0, i = 0; for (i = 0;; i++) { if (!(node = node_list[i])) { break; } - for (x = 0; x < MAX_PRI; x++) { - total += fifo_queue_size(node->fifo_list[x]); - } + total += node_caller_count(node); } if (total) { From 011882c8dda2d840862753d5133208f4dd59cc39 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 19:20:20 +0000 Subject: [PATCH 33/47] mod_fifo: Cleanup line spacing --- src/mod/applications/mod_fifo/mod_fifo.c | 149 ----------------------- 1 file changed, 149 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index c1a8b27f74..eb4c8c6d05 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -135,8 +135,6 @@ typedef enum { FIFO_APP_DID_HOOK = (1 << 2) } fifo_app_flag_t; - - static int check_caller_outbound_call(const char *key); static void add_caller_outbound_call(const char *key, switch_call_cause_t *cancel_cause); static void del_caller_outbound_call(const char *key); @@ -146,12 +144,10 @@ static void add_consumer_outbound_call(const char *key, switch_call_cause_t *can static void del_consumer_outbound_call(const char *key); static void cancel_consumer_outbound_call(const char *key, switch_call_cause_t cause); - static int check_bridge_call(const char *key); static void add_bridge_call(const char *key); static void del_bridge_call(const char *key); - switch_status_t fifo_queue_create(fifo_queue_t **queue, int size, switch_memory_pool_t *pool) { fifo_queue_t *q; @@ -167,7 +163,6 @@ switch_status_t fifo_queue_create(fifo_queue_t **queue, int size, switch_memory_ return SWITCH_STATUS_SUCCESS; } - static void change_pos(switch_event_t *event, int pos) { const char *uuid = switch_event_get_header(event, "unique-id"); @@ -289,7 +284,6 @@ static switch_status_t fifo_queue_pop_nameval(fifo_queue_t *queue, const char *n const char *j_val = switch_event_get_header(queue->data[j], name); const char *uuid = switch_event_get_header(queue->data[j], "unique-id"); if (j_val && val && !strcmp(j_val, val) && (force || !check_caller_outbound_call(uuid))) { - if (remove) { *pop = queue->data[j]; } else { @@ -360,11 +354,8 @@ static switch_status_t fifo_queue_popfly(fifo_queue_t *queue, const char *uuid) switch_mutex_unlock(queue->mutex); return SWITCH_STATUS_SUCCESS; - } - - /*! * \struct fifo_node * @@ -412,8 +403,6 @@ typedef struct fifo_node fifo_node_t; static void fifo_caller_add(fifo_node_t *node, switch_core_session_t *session); static void fifo_caller_del(const char *uuid); - - struct callback { char *buf; size_t len; @@ -724,13 +713,10 @@ static struct { outbound_strategy_t default_strategy; } globals; - - static int fifo_dec_use_count(const char *outbound_id) { int r = 0, *count; - switch_mutex_lock(globals.use_mutex); if ((count = (int *) switch_core_hash_find(globals.use_hash, outbound_id))) { if (*count > 0) { @@ -755,7 +741,6 @@ static int fifo_get_use_count(const char *outbound_id) return r; } - static int fifo_inc_use_count(const char *outbound_id) { int r = 0, *count; @@ -783,9 +768,6 @@ static void fifo_init_use_count(void) switch_mutex_unlock(globals.use_mutex); } - - - static int check_caller_outbound_call(const char *key) { int x = 0; @@ -796,10 +778,8 @@ static int check_caller_outbound_call(const char *key) x = !!switch_core_hash_find(globals.caller_orig_hash, key); switch_mutex_unlock(globals.caller_orig_mutex); return x; - } - static void add_caller_outbound_call(const char *key, switch_call_cause_t *cancel_cause) { if (!key) return; @@ -831,8 +811,6 @@ static void cancel_caller_outbound_call(const char *key, switch_call_cause_t cau switch_mutex_unlock(globals.caller_orig_mutex); } - - static int check_bridge_call(const char *key) { int x = 0; @@ -843,10 +821,8 @@ static int check_bridge_call(const char *key) x = !!switch_core_hash_find(globals.bridge_hash, key); switch_mutex_unlock(globals.bridge_mutex); return x; - } - static void add_bridge_call(const char *key) { static int marker = 1; @@ -864,7 +840,6 @@ static void del_bridge_call(const char *key) switch_mutex_unlock(globals.bridge_mutex); } - static int check_consumer_outbound_call(const char *key) { int x = 0; @@ -875,7 +850,6 @@ static int check_consumer_outbound_call(const char *key) x = !!switch_core_hash_find(globals.consumer_orig_hash, key); switch_mutex_unlock(globals.consumer_orig_mutex); return x; - } static void add_consumer_outbound_call(const char *key, switch_call_cause_t *cancel_cause) @@ -907,14 +881,10 @@ static void cancel_consumer_outbound_call(const char *key, switch_call_cause_t c *cancel_cause = cause; } switch_mutex_unlock(globals.consumer_orig_mutex); - } - - switch_cache_db_handle_t *fifo_get_db_handle(void) { - switch_cache_db_handle_t *dbh = NULL; char *dsn; @@ -939,7 +909,6 @@ static switch_status_t fifo_execute_sql_queued(char **sqlp, switch_bool_t sql_al switch_assert(sqlp && *sqlp); sql = *sqlp; - if (switch_stristr("insert", sql)) { index = 0; } @@ -955,7 +924,6 @@ static switch_status_t fifo_execute_sql_queued(char **sqlp, switch_bool_t sql_al } return SWITCH_STATUS_SUCCESS; - } #if 0 static switch_status_t fifo_execute_sql(char *sql, switch_mutex_t *mutex) @@ -1101,7 +1069,6 @@ static int node_idle_consumers(fifo_node_t *node) switch_mutex_unlock(node->mutex); return total; - } struct call_helper { @@ -1156,7 +1123,6 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses sql = switch_mprintf("delete from fifo_bridge where consumer_uuid='%q'", switch_core_session_get_uuid(consumer_session)); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); - switch_channel_set_variable(consumer_channel, "fifo_status", "WAITING"); switch_channel_set_variable(consumer_channel, "fifo_timestamp", date); @@ -1208,7 +1174,6 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses } } - static switch_status_t messagehook (switch_core_session_t *session, switch_core_session_message_t *msg) { switch_event_t *event; @@ -1250,11 +1215,9 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ goto end; } - switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_BRIDGE: { - long epoch_start = 0; char date[80] = ""; switch_time_t ts; @@ -1349,7 +1312,6 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); - epoch_start = (long)switch_epoch_time_now(NULL); ts = switch_micro_time_now(); @@ -1391,7 +1353,6 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ return SWITCH_STATUS_SUCCESS; } - static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thread, void *obj) { struct callback_helper *cbh = (struct callback_helper *) obj; @@ -1475,7 +1436,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr goto end; } - if (node) { switch_mutex_lock(node->update_mutex); node->busy = 0; @@ -1491,14 +1451,12 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS); switch_assert(ovars); - for (i = 0; i < cbh->rowcount; i++) { struct call_helper *h = cbh->rows[i]; char *parsed = NULL; int use_ent = 0; char *expanded_originate_string = switch_event_expand_headers(ovars, h->originate_string); - if (strstr(expanded_originate_string, "user/")) { switch_event_create_brackets(expanded_originate_string, '<', '>', ',', &ovars, &parsed, SWITCH_TRUE); use_ent = 1; @@ -1526,7 +1484,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr if (expanded_originate_string && expanded_originate_string != h->originate_string) { switch_safe_free(expanded_originate_string); } - } originate_string = (char *) stream.data; @@ -1589,7 +1546,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr switch_event_add_header_string(ovars, SWITCH_STACK_BOTTOM, "fifo_originate_uuid", uuid_str); - if ((export = switch_event_get_header(pop, "variable_fifo_export"))) { int argc; char *argv[100] = { 0 }; @@ -1611,7 +1567,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr switch_safe_free(mydata); } - if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { switch_core_session_t *session; if (id && (session = switch_core_session_locate(id))) { @@ -1637,7 +1592,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count+1 where uuid='%s'", h->uuid); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); - } if (!total) goto end; @@ -1665,7 +1619,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr del_caller_outbound_call(id); - if (status != SWITCH_STATUS_SUCCESS || cause != SWITCH_CAUSE_SUCCESS) { const char *acceptable = "false"; @@ -1681,7 +1634,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr "where uuid='%q' and ring_count > 0", h->uuid); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); } - } break; default: @@ -1694,7 +1646,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr "next_avail=%ld + lag + 1 where uuid='%q' and ring_count > 0", (long) switch_epoch_time_now(NULL) + node->retry_delay, h->uuid); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); - } } } @@ -1730,7 +1681,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr switch_event_fire(&event); } - switch_channel_set_variable(channel, "fifo_pop_order", NULL); app_name = "fifo"; @@ -1744,9 +1694,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr switch_core_session_rwunlock(session); - - - for (i = 0; i < cbh->rowcount; i++) { struct call_helper *h = cbh->rows[i]; char *sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1 where uuid='%q' and ring_count > 0", h->uuid); @@ -1765,7 +1712,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr switch_thread_rwlock_unlock(node->rwlock); } - for (i = 0; i < cbh->rowcount; i++) { struct call_helper *h = cbh->rows[i]; del_consumer_outbound_call(h->uuid); @@ -1817,7 +1763,6 @@ static void *SWITCH_THREAD_FUNC outbound_enterprise_thread_run(switch_thread_t * globals.threads++; switch_mutex_unlock(globals.mutex); - switch_mutex_lock(globals.mutex); node = switch_core_hash_find(globals.fifo_hash, h->node_name); switch_thread_rwlock_rdlock(node->rwlock); @@ -1849,7 +1794,6 @@ static void *SWITCH_THREAD_FUNC outbound_enterprise_thread_run(switch_thread_t * "origination_caller_id_name=Queue,origination_caller_id_number='Queue: %q'}%s", node->name, node->name, node->name, expanded_originate_string); } - } if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { @@ -1861,14 +1805,12 @@ static void *SWITCH_THREAD_FUNC outbound_enterprise_thread_run(switch_thread_t * switch_event_fire(&event); } - sql = switch_mprintf("update fifo_outbound set ring_count=ring_count+1 where uuid='%s'", h->uuid); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); status = switch_ivr_originate(NULL, &session, &cause, originate_string, h->timeout, NULL, NULL, NULL, NULL, ovars, SOF_NONE, NULL); if (status != SWITCH_STATUS_SUCCESS) { - sql = switch_mprintf("update fifo_outbound set ring_count=ring_count-1, " "outbound_fail_count=outbound_fail_count+1, next_avail=%ld + lag + 1 where uuid='%q'", (long) switch_epoch_time_now(NULL) + (node ? node->retry_delay : 0), h->uuid); @@ -1901,7 +1843,6 @@ static void *SWITCH_THREAD_FUNC outbound_enterprise_thread_run(switch_thread_t * switch_event_fire(&event); } - if ((member_wait = switch_channel_get_variable(channel, "fifo_member_wait")) || (member_wait = switch_channel_get_variable(channel, "member_wait"))) { if (strcasecmp(member_wait, "wait") && strcasecmp(member_wait, "nowait")) { member_wait = NULL; @@ -1971,12 +1912,10 @@ static int place_call_ringall_callback(void *pArg, int argc, char **argv, char * } return 0; - } static int place_call_enterprise_callback(void *pArg, int argc, char **argv, char **columnNames) { - int *need = (int *) pArg; switch_thread_t *thread; @@ -1992,7 +1931,6 @@ static int place_call_enterprise_callback(void *pArg, int argc, char **argv, cha h->originate_string = switch_core_strdup(h->pool, argv[2]); h->timeout = atoi(argv[5]); - switch_threadattr_create(&thd_attr, h->pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); @@ -2007,7 +1945,6 @@ static void find_consumers(fifo_node_t *node) { char *sql; - sql = switch_mprintf("select uuid, fifo_name, originate_string, simo_count, use_count, timeout, lag, " "next_avail, expires, static, outbound_call_count, outbound_fail_count, hostname " "from fifo_outbound " @@ -2016,8 +1953,6 @@ static void find_consumers(fifo_node_t *node) node->name, (long) switch_epoch_time_now(NULL) ); - - switch(node->outbound_strategy) { case NODE_STRATEGY_ENTERPRISE: { @@ -2028,7 +1963,6 @@ static void find_consumers(fifo_node_t *node) } fifo_execute_sql_callback(globals.sql_mutex, sql, place_call_enterprise_callback, &need); - } break; case NODE_STRATEGY_RINGALL: @@ -2057,14 +1991,12 @@ static void find_consumers(fifo_node_t *node) } else { switch_core_destroy_memory_pool(&pool); } - } break; default: break; } - switch_safe_free(sql); } @@ -2100,10 +2032,8 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o switch_event_destroy(&pop); } } - } - if (this_node->ready == 0 && switch_thread_rwlock_trywrlock(this_node->rwlock) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", this_node->name); @@ -2142,7 +2072,6 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o this_node->name, ppl_waiting, consumer_total, idle_consumers, this_node->ring_consumer_count, this_node->outbound_priority); } - if ((ppl_waiting - this_node->ring_consumer_count > 0) && (!consumer_total || !idle_consumers)) { found++; find_consumers(this_node); @@ -2151,7 +2080,6 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o } } - if (++cur_priority > 10) { cur_priority = 1; } @@ -2202,7 +2130,6 @@ static void check_cancel(fifo_node_t *node) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Outbound call count (%d) exceeds required value for queue %s (%d), " "Ending extraneous calls\n", node->ring_consumer_count, node->name, ppl_waiting); - switch_core_session_hupall_matching_var("fifo_hangup_check", node->name, SWITCH_CAUSE_ORIGINATOR_CANCEL); } } @@ -2271,7 +2198,6 @@ static void pres_event_handler(switch_event_t *event) dup_node_name = switch_mprintf("%q@%q", node_name, domain_name); - switch_mutex_lock(globals.mutex); if (!(node = switch_core_hash_find(globals.fifo_hash, node_name)) && !(node = switch_core_hash_find(globals.fifo_hash, dup_node_name))) { node = create_node(node_name, 0, globals.sql_mutex); @@ -2322,7 +2248,6 @@ static uint32_t fifo_add_outbound(const char *node_name, const char *url, uint32 switch_thread_rwlock_unlock(node->rwlock); return i; - } SWITCH_STANDARD_API(fifo_check_bridge_function) @@ -2357,17 +2282,14 @@ SWITCH_STANDARD_API(fifo_add_outbound_function) stream->write_function(stream, "%d", fifo_add_outbound(argv[0], argv[1], priority)); - free(data); return SWITCH_STATUS_SUCCESS; - fail: free(data); stream->write_function(stream, "0"); return SWITCH_STATUS_SUCCESS; - } static void dec_use_count(switch_core_session_t *session, const char *type) @@ -2381,7 +2303,6 @@ static void dec_use_count(switch_core_session_t *session, const char *type) if ((outbound_id = switch_channel_get_variable(channel, "fifo_outbound_uuid"))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s untracking call on uuid %s!\n", switch_channel_get_name(channel), outbound_id); - sql = switch_mprintf("delete from fifo_bridge where consumer_uuid='%q'", switch_core_session_get_uuid(session)); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); @@ -2468,7 +2389,6 @@ SWITCH_STANDARD_APP(fifo_track_call_function) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s tracking call on uuid %s!\n", switch_channel_get_name(channel), data); - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { col1 = "manual_calls_in_count"; col2 = "manual_calls_in_total_count"; @@ -2503,7 +2423,6 @@ SWITCH_STANDARD_APP(fifo_track_call_function) } } - static void fifo_caller_add(fifo_node_t *node, switch_core_session_t *session) { char *sql; @@ -2531,11 +2450,8 @@ static void fifo_caller_del(const char *uuid) } fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); - } - - typedef enum { STRAT_MORE_PPL, STRAT_WAITING_LONGER, @@ -2621,7 +2537,6 @@ SWITCH_STANDARD_APP(fifo_function) } } - if (!(node = switch_core_hash_find(globals.fifo_hash, nlist[i]))) { node = create_node(nlist[i], importance, globals.sql_mutex); node->ready = 1; @@ -2735,7 +2650,6 @@ SWITCH_STANDARD_APP(fifo_function) switch_event_create(&call_event, SWITCH_EVENT_CHANNEL_DATA); switch_channel_event_set_data(channel, call_event); - fifo_queue_push(node->fifo_list[p], call_event); fifo_caller_add(node, session); in_table = 1; @@ -2811,7 +2725,6 @@ SWITCH_STANDARD_APP(fifo_function) aborted = 1; goto abort; } - } if (!serviced_uuid && switch_channel_ready(channel)) { @@ -2862,7 +2775,6 @@ SWITCH_STANDARD_APP(fifo_function) send_presence(node); check_cancel(node); switch_mutex_unlock(globals.mutex); - } if ((switch_true(switch_channel_get_variable(channel, "fifo_caller_exit_to_orbit")) || cd.do_orbit) && cd.orbit_exten) { @@ -2878,7 +2790,6 @@ SWITCH_STANDARD_APP(fifo_function) cancel_caller_outbound_call(switch_core_session_get_uuid(session), SWITCH_CAUSE_ORIGINATOR_CANCEL); goto done; - } else { /* consumer */ switch_event_t *pop = NULL; switch_frame_t *read_frame; @@ -3026,7 +2937,6 @@ SWITCH_STANDARD_APP(fifo_function) } if ((waiting = node_caller_count(node))) { - if (!importance || node->importance > importance) { if (strat == STRAT_WAITING_LONGER) { if (node->start_waiting < longest) { @@ -3164,7 +3074,6 @@ SWITCH_STANDARD_APP(fifo_function) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Outbound-URL", url); switch_event_fire(&event); } - } else { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event); @@ -3177,7 +3086,6 @@ SWITCH_STANDARD_APP(fifo_function) url = NULL; caller_uuid = switch_core_session_strdup(session, switch_core_session_get_uuid(other_session)); } - } else { if ((other_session = switch_core_session_locate(caller_uuid))) { switch_channel_t *other_channel = switch_core_session_get_channel(other_session); @@ -3218,7 +3126,6 @@ SWITCH_STANDARD_APP(fifo_function) } } - switch_channel_set_variable(other_channel, "fifo_serviced_by", my_id); switch_channel_set_variable(other_channel, "fifo_serviced_uuid", switch_core_session_get_uuid(session)); switch_channel_set_flag(other_channel, CF_BREAK); @@ -3236,7 +3143,6 @@ SWITCH_STANDARD_APP(fifo_function) const char *arg = switch_channel_get_variable(other_channel, "current_application_data"); switch_caller_extension_t *extension = NULL; - switch_channel_set_variable_printf(channel, "last_sent_callee_id_name", "%s (AGENT FAIL)", switch_channel_get_variable(other_channel, "caller_id_name")); switch_channel_set_variable(channel, "last_sent_callee_id_number", switch_channel_get_variable(other_channel, "caller_id_number")); @@ -3277,7 +3183,6 @@ SWITCH_STANDARD_APP(fifo_function) } } - switch_channel_step_caller_profile(channel); switch_channel_step_caller_profile(other_channel); @@ -3287,20 +3192,15 @@ SWITCH_STANDARD_APP(fifo_function) switch_channel_set_originator_caller_profile(other_channel, switch_caller_profile_clone(other_session, originator_cp)); switch_channel_set_originatee_caller_profile(channel, switch_caller_profile_clone(session, originatee_cp)); - originator_cp->callee_id_name = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_name); originator_cp->callee_id_number = switch_core_strdup(originator_cp->pool, originatee_cp->callee_id_number); - originatee_cp->callee_id_name = switch_core_strdup(originatee_cp->pool, originatee_cp->caller_id_name); originatee_cp->callee_id_number = switch_core_strdup(originatee_cp->pool, originatee_cp->caller_id_number); originatee_cp->caller_id_name = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_name); originatee_cp->caller_id_number = switch_core_strdup(originatee_cp->pool, originator_cp->caller_id_number); - - - ts = switch_micro_time_now(); switch_time_exp_lt(&tm, ts); epoch_start = (long)switch_epoch_time_now(NULL); @@ -3330,7 +3230,6 @@ SWITCH_STANDARD_APP(fifo_function) switch_process_import(session, other_channel, "fifo_caller_consumer_import", switch_channel_get_variable(channel, "fifo_import_prefix")); switch_process_import(other_session, channel, "fifo_consumer_caller_import", switch_channel_get_variable(other_channel, "fifo_import_prefix")); - if (outbound_id) { cancel_consumer_outbound_call(outbound_id, SWITCH_CAUSE_ORIGINATOR_CANCEL); add_bridge_call(outbound_id); @@ -3338,10 +3237,8 @@ SWITCH_STANDARD_APP(fifo_function) sql = switch_mprintf("update fifo_outbound set stop_time=0,start_time=%ld,use_count=use_count+1,outbound_fail_count=0 where uuid='%s'", switch_epoch_time_now(NULL), outbound_id); - fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); fifo_inc_use_count(outbound_id); - } if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { @@ -3358,8 +3255,6 @@ SWITCH_STANDARD_APP(fifo_function) switch_event_fire(&event); } - - if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]); @@ -3378,7 +3273,6 @@ SWITCH_STANDARD_APP(fifo_function) switch_event_fire(&event); } - add_bridge_call(switch_core_session_get_uuid(other_session)); add_bridge_call(switch_core_session_get_uuid(session)); @@ -3394,10 +3288,8 @@ SWITCH_STANDARD_APP(fifo_function) (long) switch_epoch_time_now(NULL) ); - fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); - switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(other_session)); switch_channel_set_variable(other_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(session)); @@ -3430,10 +3322,8 @@ SWITCH_STANDARD_APP(fifo_function) del_bridge_call(outbound_id); fifo_dec_use_count(outbound_id); - } - if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { uint64_t hold_usec = 0, tt_usec = 0; switch_channel_event_set_data(channel, event); @@ -3462,7 +3352,6 @@ SWITCH_STANDARD_APP(fifo_function) del_bridge_call(switch_core_session_get_uuid(session)); del_bridge_call(switch_core_session_get_uuid(other_session)); - if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]); @@ -3500,7 +3389,6 @@ SWITCH_STANDARD_APP(fifo_function) sql = switch_mprintf("delete from fifo_bridge where consumer_uuid='%q'", switch_core_session_get_uuid(session)); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_FALSE); - if (switch_channel_ready(channel)) { switch_core_media_bug_pause(session); } @@ -3526,7 +3414,6 @@ SWITCH_STANDARD_APP(fifo_function) switch_core_session_rwunlock(other_session); - if (!do_wait || !switch_channel_ready(channel)) { break; } @@ -3584,7 +3471,6 @@ SWITCH_STANDARD_APP(fifo_function) if ((terminator == *fifo_consumer_wrapup_key) || !(switch_channel_ready(channel))) { break; } - } } else if (fifo_consumer_wrapup_time && (zstr(fifo_consumer_wrapup_key) || !strcmp(buf, fifo_consumer_wrapup_key))) { while (switch_channel_ready(channel)) { @@ -3631,7 +3517,6 @@ SWITCH_STANDARD_APP(fifo_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s is still alive, tracking call.\n", switch_channel_get_name(channel)); fifo_track_call_function(session, outbound_id); } - } done: @@ -3704,14 +3589,12 @@ static int xml_callback(void *pArg, int argc, char **argv, char **columnNames) } } - if (atoi(argv[13])) { arg = 17; } else { arg = 18; } - if ((etime = atol(argv[arg]))) { switch_size_t retsize; switch_time_exp_lt(&tm, switch_time_from_sec(etime)); @@ -3720,7 +3603,6 @@ static int xml_callback(void *pArg, int argc, char **argv, char **columnNames) switch_set_string(atime, "now"); } - x_out = switch_xml_add_child_d(h->xml, h->tag, c_off++); switch_xml_set_attr_d(x_out, "simo", argv[3]); switch_xml_set_attr_d(x_out, "use_count", argv[4]); @@ -3769,7 +3651,6 @@ static int xml_callback(void *pArg, int argc, char **argv, char **columnNames) switch_xml_set_attr_d(x_out, "stop-time", tb); } - switch_xml_set_attr_d(x_out, "next-available", expires); switch_xml_set_txt_d(x_out, argv[2]); @@ -3783,7 +3664,6 @@ static int xml_outbound(switch_xml_t xml, fifo_node_t *node, char *container, ch char *sql; if (!strcmp(node->name, MANUAL_QUEUE_NAME)) { - sql = switch_mprintf("select uuid, '%s', originate_string, simo_count, use_count, timeout," "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count," "hostname, taking_calls, status, outbound_call_total_count, outbound_fail_total_count, active_time, inactive_time," @@ -3794,8 +3674,6 @@ static int xml_outbound(switch_xml_t xml, fifo_node_t *node, char *container, ch "hostname, taking_calls, status, outbound_call_total_count, outbound_fail_total_count, active_time, inactive_time," "manual_calls_out_count, manual_calls_in_count, manual_calls_out_total_count, manual_calls_in_total_count", MANUAL_QUEUE_NAME); - - } else { sql = switch_mprintf("select uuid, fifo_name, originate_string, simo_count, use_count, timeout, " "lag, next_avail, expires, static, outbound_call_count, outbound_fail_count, " @@ -3822,7 +3700,6 @@ static int xml_outbound(switch_xml_t xml, fifo_node_t *node, char *container, ch return h.cc_off; } - static int xml_bridge_callback(void *pArg, int argc, char **argv, char **columnNames) { struct xml_helper *h = (struct xml_helper *) pArg; @@ -3844,7 +3721,6 @@ static int xml_bridge_callback(void *pArg, int argc, char **argv, char **columnN switch_set_string(exp_buf, "now"); } - x_bridge = switch_xml_add_child_d(h->xml, h->tag, h->row_off++); switch_xml_set_attr_d(x_bridge, "fifo_name", argv[0]); @@ -3861,8 +3737,6 @@ static int xml_bridge_callback(void *pArg, int argc, char **argv, char **columnN encoded = switch_url_encode(argv[3], url_buf, sizeof(url_buf)); switch_xml_set_attr_d(x_caller, "caller_id_number", encoded); - - if (h->verbose) { if ((session = switch_core_session_locate(argv[1]))) { x_cdr = switch_xml_add_child_d(x_caller, "cdr", 0); @@ -3976,7 +3850,6 @@ static int xml_hash(switch_xml_t xml, switch_hash_t *hash, char *container, char return cc_off; } - static int xml_caller(switch_xml_t xml, fifo_node_t *node, char *container, char *tag, int cc_off, int verbose) { switch_xml_t x_tmp, x_caller, x_cp; @@ -3993,7 +3866,6 @@ static int xml_caller(switch_xml_t xml, fifo_node_t *node, char *container, char switch_mutex_lock(q->mutex); for (i = 0; i < q->idx; i++) { - int c_off = 0, d_off = 0; const char *status; const char *ts; @@ -4045,7 +3917,6 @@ static int xml_caller(switch_xml_t xml, fifo_node_t *node, char *container, char switch_snprintf(sl, sizeof(sl), "%d", x); switch_xml_set_attr_d_buf(x_caller, "slot", sl); - if (verbose) { if (!(x_cp = switch_xml_add_child_d(x_caller, "cdr", d_off++))) { abort(); @@ -4104,7 +3975,6 @@ static void list_node(fifo_node_t *node, switch_xml_t x_report, int *off, int ve cc_off = xml_bridges(x_fifo, node, "bridges", "bridge", cc_off, verbose); } - void dump_hash(switch_hash_t *hash, switch_stream_handle_t *stream) { switch_hash_index_t *hi; @@ -4121,8 +3991,6 @@ void dump_hash(switch_hash_t *hash, switch_stream_handle_t *stream) void node_dump(switch_stream_handle_t *stream) { - - switch_hash_index_t *hi; fifo_node_t *node; void *val; @@ -4161,12 +4029,8 @@ void node_dump(switch_stream_handle_t *stream) dump_hash(globals.bridge_hash, stream); switch_mutex_unlock(globals.mutex); - - } - - #define FIFO_API_SYNTAX "list|list_verbose|count|debug|status|importance []|reparse [del_all]" SWITCH_STANDARD_API(fifo_api_function) { @@ -4188,7 +4052,6 @@ SWITCH_STANDARD_API(fifo_api_function) switch_assert(data); } - switch_mutex_lock(globals.mutex); if (zstr(cmd) || (argc = switch_separate_string(data, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 1 || !argv[0]) { @@ -4245,7 +4108,6 @@ SWITCH_STANDARD_API(fifo_api_function) stream->write_function(stream, "%s\n", xml_text); switch_xml_free(x_report); switch_safe_free(xml_text); - } else if (!strcasecmp(argv[0], "importance")) { if (argv[1] && (node = switch_core_hash_find(globals.fifo_hash, argv[1]))) { int importance = 0; @@ -4314,7 +4176,6 @@ SWITCH_STANDARD_API(fifo_api_function) return SWITCH_STATUS_SUCCESS; } - const char outbound_sql[] = "create table fifo_outbound (\n" " uuid varchar(255),\n" @@ -4345,7 +4206,6 @@ const char outbound_sql[] = " stop_time integer not null default 0\n" ");\n"; - const char bridge_sql[] = "create table fifo_bridge (\n" " fifo_name varchar(1024) not null,\n" @@ -4369,8 +4229,6 @@ const char callers_sql[] = ");\n" ; - - static void extract_fifo_outbound_uuid(char *string, char *uuid, switch_size_t len) { switch_event_t *ovars; @@ -4378,7 +4236,6 @@ static void extract_fifo_outbound_uuid(char *string, char *uuid, switch_size_t l const char *fifo_outbound_uuid; switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS); - switch_event_create_brackets(string, '{', '}', ',', &ovars, &parsed, SWITCH_TRUE); if ((fifo_outbound_uuid = switch_event_get_header(ovars, "fifo_outbound_uuid"))) { @@ -4665,7 +4522,6 @@ static switch_status_t load_config(int reload, int del_all) return status; } - static void fifo_member_add(char *fifo_name, char *originate_string, int simo_count, int timeout, int lag, time_t expires, int taking_calls) { char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 }; @@ -4686,7 +4542,6 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co switch_assert(sql); fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); - switch_mutex_lock(globals.mutex); if (!(node = switch_core_hash_find(globals.fifo_hash, fifo_name))) { node = create_node(fifo_name, 0, globals.sql_mutex); @@ -4732,7 +4587,6 @@ static void fifo_member_del(char *fifo_name, char *originate_string) if (!fifo_name) return; - if (switch_stristr("fifo_outbound_uuid=", originate_string)) { extract_fifo_outbound_uuid(originate_string, digest, sizeof(digest)); } else { @@ -4844,7 +4698,6 @@ SWITCH_STANDARD_API(fifo_member_api_function) free(mydata); return SWITCH_STATUS_SUCCESS; - } SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load) @@ -4890,7 +4743,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load) return status; } - /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); SWITCH_ADD_APP(app_interface, "fifo", "Park with FIFO", FIFO_DESC, fifo_function, FIFO_USAGE, SAF_NONE); @@ -4946,7 +4798,6 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown) this_node = node; node = node->next; - switch_mutex_lock(this_node->update_mutex); switch_mutex_lock(this_node->mutex); for (x = 0; x < MAX_PRI; x++) { From 64144d73a371452d0119fe341b8b80410dfef939 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 19:46:55 +0000 Subject: [PATCH 34/47] mod_fifo: Refactor to avoid a memory allocation --- src/mod/applications/mod_fifo/mod_fifo.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index eb4c8c6d05..f1a1474882 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -999,8 +999,6 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu char outbound_count[80] = ""; callback_t cbt = { 0 }; char *sql = NULL; - char *domain_name = NULL; - if (!globals.running) { return NULL; } @@ -1013,8 +1011,7 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu node->name = switch_core_strdup(node->pool, name); if (!strchr(name, '@')) { - domain_name = switch_core_get_domain(SWITCH_TRUE); - node->domain_name = switch_core_strdup(node->pool, domain_name); + node->domain_name = switch_core_strdup(node->pool, switch_core_get_domain(SWITCH_FALSE)); } for (x = 0; x < MAX_PRI; x++) { @@ -1043,8 +1040,6 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu globals.nodes = node; switch_mutex_unlock(globals.mutex); - switch_safe_free(domain_name); - return node; } From a24b0b739f9536e5e07894c688a6ca40534a68b1 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 19:58:26 +0000 Subject: [PATCH 35/47] mod_fifo: Avoid getting time twice We were simply discarding unused the first time we retrieved here. --- src/mod/applications/mod_fifo/mod_fifo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index f1a1474882..11d5e4a987 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1111,7 +1111,6 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses use_count = fifo_get_use_count(outbound_id); } - ts = switch_micro_time_now(); switch_time_exp_lt(&tm, ts); switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); From 48acd9fe66604778bdc295ef617d9579f0ba09ff Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 20:30:39 +0000 Subject: [PATCH 36/47] mod_fifo: Note source of unexplained constant --- src/mod/applications/mod_fifo/mod_fifo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 11d5e4a987..3d8fecc442 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1186,6 +1186,7 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ case SWITCH_MESSAGE_INDICATE_BRIDGE: case SWITCH_MESSAGE_INDICATE_UNBRIDGE: if (msg->numeric_arg == 42) { + /* See audio_bridge_thread() for source of 42 constant. */ goto end; } if ((caller_session = switch_core_session_locate(msg->string_arg))) { From 343aee2dd819cf893bc3787ec7010f1ee3d64f70 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 20:46:59 +0000 Subject: [PATCH 37/47] mod_fifo: Comment manual call tracking session handler --- src/mod/applications/mod_fifo/mod_fifo.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 3d8fecc442..c52f328587 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1083,6 +1083,8 @@ struct callback_helper { int ready; }; +/*!\brief Handle unbridging of manually tracked calls + */ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_session_t *caller_session) { switch_channel_t *consumer_channel = switch_core_session_get_channel(consumer_session); @@ -1168,6 +1170,8 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses } } +/*!\brief Handle session messages for manually tracked calls + */ static switch_status_t messagehook (switch_core_session_t *session, switch_core_session_message_t *msg) { switch_event_t *event; From 80ccaf3450f2dc24695b5f3abbc082c532df6a2a Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 21:19:56 +0000 Subject: [PATCH 38/47] mod_fifo: Remove duplicate check in ringall strategy We already checked the number of usable rows, and nothing has changed. --- src/mod/applications/mod_fifo/mod_fifo.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index c52f328587..f8496a74f1 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1593,8 +1593,6 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr fifo_execute_sql_queued(&sql, SWITCH_TRUE, SWITCH_TRUE); } - if (!total) goto end; - if (!globals.allow_transcoding && !switch_true(switch_event_get_header(pop, "variable_fifo_allow_transcoding")) && (codec = switch_event_get_header(pop, "variable_rtp_use_codec_name"))) { const char *rate = switch_event_get_header(pop, "variable_rtp_use_codec_rate"); From 0c25c3deb923351ed33c86c2354da9957126df34 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 26 May 2014 22:57:12 +0000 Subject: [PATCH 39/47] mod_fifo: Document node_thread_run() --- src/mod/applications/mod_fifo/mod_fifo.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index f8496a74f1..f1902eb636 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1997,6 +1997,20 @@ static void find_consumers(fifo_node_t *node) switch_safe_free(sql); } +/*\brief Continuously attempt to deliver calls to outbound members + * + * For each outbound priority level 1-10, find fifo nodes with a + * matching priority. For each of those nodes with outbound members, + * run `find_consumers()` if the fifo node has calls needing to be + * delivered and not enough ready and waiting inbound consumers. + * + * In the event of nothing needing to be done, each cycle starts at + * priority 1 and ends at priority 10, yielding for one second + * afterward. We also yield after initiating outbound calls, starting + * again where we left off on the next node. + * + * We also take care of cleaning up after nodes queued for deletion. + */ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *obj) { fifo_node_t *node, *last, *this_node; From 1b5a1c1e1d9398db32962fd70f62ca047073dc94 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 27 May 2014 03:34:18 +0000 Subject: [PATCH 40/47] mod_fifo: Document find_consumers() --- src/mod/applications/mod_fifo/mod_fifo.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index f1902eb636..61152afb0a 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1938,6 +1938,18 @@ static int place_call_enterprise_callback(void *pArg, int argc, char **argv, cha return *need ? 0 : -1; } +/*!\brief Find outbound members to call for a given fifo node + * + * We're given a fifo node that has callers to be delivered to agents. + * Our job is to find available outbound members and pass them to the + * appropriate outbound strategy handler. + * + * The ringall strategy handler needs the full list of members to do + * its job, so we first let `place_call_ringall_callback` accumulate + * the results. The enterprise strategy handler can simply take each + * member one at a time, so the `place_call_enterprise_callback` takes + * care of invoking the handler. + */ static void find_consumers(fifo_node_t *node) { char *sql; From e2596b3f30271a416a6125d5e4c8035cf54e7d1d Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 27 May 2014 03:32:54 +0000 Subject: [PATCH 41/47] mod_fifo: Document the ringall strategy --- src/mod/applications/mod_fifo/mod_fifo.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 61152afb0a..e078deeb16 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1352,6 +1352,20 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ return SWITCH_STATUS_SUCCESS; } +/*!\brief Create calls to outbound members with ringall strategy + * + * A fifo node has been selected for us and we've been given a list of + * outbound members to ring. We're going to pick a single caller by + * searching through the fifo node queues in order of priority + * (`fifo_priority`) from lowest to highest. We'll look first for + * callers with fifo_vip=true. Finding none, we'll consider the + * plebs. + * + * Once we have a caller to service, we'll set fifo_bridge_uuid for + * that caller to let the fifo application in on our decision. Our + * job being done, we'll let the fifo application deal with the + * remaining details. + */ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thread, void *obj) { struct callback_helper *cbh = (struct callback_helper *) obj; @@ -1887,6 +1901,9 @@ static void *SWITCH_THREAD_FUNC outbound_enterprise_thread_run(switch_thread_t * return NULL; } +/*!\brief Extract the outbound member results and accumulate them for + * the ringall strategy handler + */ static int place_call_ringall_callback(void *pArg, int argc, char **argv, char **columnNames) { struct callback_helper *cbh = (struct callback_helper *) pArg; @@ -2991,6 +3008,7 @@ SWITCH_STANDARD_APP(fifo_function) check = switch_channel_get_variable(channel, "fifo_bridge_uuid_required"); + /* Handle predestined calls, including calls from the ringall strategy */ if ((varval = switch_channel_get_variable(channel, "fifo_bridge_uuid"))) { if (check_bridge_call(varval) && switch_true(check)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Call has already been answered\n", From 96012ffb3a2b26b3b53d592dfc45c69f61bcb8a1 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 27 May 2014 03:33:55 +0000 Subject: [PATCH 42/47] mod_fifo: Document the enterprise strategy --- src/mod/applications/mod_fifo/mod_fifo.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index e078deeb16..5671ad5754 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1751,6 +1751,15 @@ static void *SWITCH_THREAD_FUNC outbound_ringall_thread_run(switch_thread_t *thr return NULL; } +/*!\brief Send a call to an outbound member with the enterprise strategy + * + * A fifo and an outbound member have been picked out for us and our + * job is to create a channel to the member and deliver that channel + * into the `fifo out` application. + * + * We haven't picked a caller yet, and we won't do so here. We'll let + * the fifo application take care of that work. + */ static void *SWITCH_THREAD_FUNC outbound_enterprise_thread_run(switch_thread_t *thread, void *obj) { struct call_helper *h = (struct call_helper *) obj; @@ -1928,6 +1937,9 @@ static int place_call_ringall_callback(void *pArg, int argc, char **argv, char * return 0; } +/*!\brief Extract the outbound member results and invoke the + * enterprise strategy handler + */ static int place_call_enterprise_callback(void *pArg, int argc, char **argv, char **columnNames) { int *need = (int *) pArg; From 431d7d97c7c4bf35af2fb135d545e48649e21d78 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 27 May 2014 04:15:44 +0000 Subject: [PATCH 43/47] mod_fifo: Document effect of fifo strategy and importance --- src/mod/applications/mod_fifo/mod_fifo.c | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 5671ad5754..7d0151f428 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -2983,6 +2983,33 @@ SWITCH_STANDARD_APP(fifo_function) } } + /* Before we can pick a caller we have to decide on a fifo + node to service if the consumer can service more than + one. + + If all fifos have an importance of zero, we'll find the + first node that wins based on the chosen strategy. + + The `waiting_longer` strategy will choose the node that + hasn't been empty for the longest time. + + The `more_ppl` strategy will choose the node that has + the most people waiting. + + If a node has an importance value set, it will cause us + to ignore later nodes with equivalent or lower + importance values. This means that a node with the + same importance that would otherwise win based on the + strategy will not be considered at all if it comes + later in the list. Note also that the high importance + node may still lose if a considered fifo earlier in the + list beats it per the strategy. + + Note that when the consumer has been delivered by an + outbound strategy there will only be one fifo node + passed to us, so neither the importance nor the + strategy here will have any effect. + */ for (i = 0; i < node_count; i++) { if (!(node = node_list[i])) { continue; From 06805452d833c6e3cd374b1f3dc8376487a43ca6 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 27 May 2014 06:55:38 +0000 Subject: [PATCH 44/47] mod_fifo: Cleanup documentation formatting --- src/mod/applications/mod_fifo/mod_fifo.c | 26 +++++++++++------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 7d0151f428..d1a1872cf3 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -204,9 +204,9 @@ static int fifo_queue_size(fifo_queue_t *queue) /*! * \param remove Whether to remove the popped event from the queue - * If remove is 0, do not remove the popped event. If it is 1, remove - * it if it is not an event for an outbound caller. If it is 2, - * always remove it. + * If remove is 0, do not remove the popped event. If it is 1, + * remove it if it is not an event for an outbound caller. If it is + * 2, always remove it. */ static switch_status_t fifo_queue_pop(fifo_queue_t *queue, switch_event_t **pop, int remove) { @@ -250,7 +250,7 @@ static switch_status_t fifo_queue_pop(fifo_queue_t *queue, switch_event_t **pop, return SWITCH_STATUS_SUCCESS; } -/*! \brief Remove matching event from queue +/*!\brief Remove matching event from queue * * Each event in the queue will be checked to see whether it has a * header equal to name whose value is equal to val. If it does, that @@ -313,7 +313,7 @@ static switch_status_t fifo_queue_pop_nameval(fifo_queue_t *queue, const char *n return SWITCH_STATUS_SUCCESS; } -/*! \brief Destroy event with given uuid and remove it from queue +/*!\brief Destroy event with given uuid and remove it from queue * * Elements of the queue are searched until a matching uuid is found. * That uuid is then destroyed and removed from the queue. The @@ -356,8 +356,7 @@ static switch_status_t fifo_queue_popfly(fifo_queue_t *queue, const char *uuid) return SWITCH_STATUS_SUCCESS; } -/*! - * \struct fifo_node +/*!\struct fifo_node * * \var fifo_node::outbound_name * \brief Name of fifo in caller ID @@ -446,7 +445,7 @@ static int sql2str_callback(void *pArg, int argc, char **argv, char **columnName return 0; } -/*! \brief Handler for consumer DTMF +/*!\brief Handler for consumer DTMF * * When `fifo_consumer_exit_key` is pressed by the consumer we hangup * on the caller (unless we've put the caller on hold). The default @@ -502,7 +501,7 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit return SWITCH_STATUS_SUCCESS; } -/*! \brief Handler for caller DTMF +/*!\brief Handler for caller DTMF * * The channel variable `fifo_caller_exit_key` can be set to one or * more digits that when pressed will cause the caller to exit from @@ -588,7 +587,7 @@ struct fifo_chime_data { typedef struct fifo_chime_data fifo_chime_data_t; -/*! \brief Enforce the `fifo_orbit_timeout` +/*!\brief Enforce the `fifo_orbit_timeout` * * If the caller has been waiting longer than the `fifo_orbit_timeout` * we break out so the orbit can do something else with the call. @@ -605,7 +604,7 @@ static switch_status_t chime_read_frame_callback(switch_core_session_t *session, return SWITCH_STATUS_SUCCESS; } -/*! \brief Handle chimes and timeouts for callers +/*!\brief Handle chimes and timeouts for callers * * Play back the chimes in order spaced out by the given `freq` while * ensuring that we don't exceed the `orbit_timeout`. @@ -653,7 +652,7 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session return chime_read_frame_callback(session, frame, user_data); } -/*! \brief Handler for waiting consumers +/*!\brief Handler for waiting consumers * * In `user_data` we'll be passed an array of fifo_nodes representing * the fifos for which this consumer will accept calls. If any of @@ -4368,8 +4367,7 @@ static switch_status_t read_config_file(switch_xml_t *xml, switch_xml_t *cfg) { return SWITCH_STATUS_SUCCESS; } -/*! - * Load or reload the configuration +/*!\brief Load or reload the configuration * * On the initial load, non-static members are preserved unless the * parameter `delete-all-outbound-members-on-startup` is set. The From 42e9615900fa5459f5c2beaeac0c5436cdf2af17 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 27 May 2014 08:09:25 +0000 Subject: [PATCH 45/47] mod_fifo: Add missing tab completions --- src/mod/applications/mod_fifo/mod_fifo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index d1a1872cf3..2250c805b1 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4833,6 +4833,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load) switch_console_set_complete("add fifo list"); switch_console_set_complete("add fifo list_verbose"); switch_console_set_complete("add fifo count"); + switch_console_set_complete("add fifo debug"); + switch_console_set_complete("add fifo status"); switch_console_set_complete("add fifo has_outbound"); switch_console_set_complete("add fifo importance"); switch_console_set_complete("add fifo reparse"); From 144fea57b213d3a45b6f6938de000740c34788d1 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 27 May 2014 08:10:51 +0000 Subject: [PATCH 46/47] mod_fifo: Add missing has_outbound to docstring --- src/mod/applications/mod_fifo/mod_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 2250c805b1..fd25b3248f 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -4110,7 +4110,7 @@ void node_dump(switch_stream_handle_t *stream) switch_mutex_unlock(globals.mutex); } -#define FIFO_API_SYNTAX "list|list_verbose|count|debug|status|importance []|reparse [del_all]" +#define FIFO_API_SYNTAX "list|list_verbose|count|debug|status|has_outbound|importance []|reparse [del_all]" SWITCH_STANDARD_API(fifo_api_function) { fifo_node_t *node; From 00b25baa421d7104ba9aee39ce8351f38b78d3d0 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 27 May 2014 17:33:05 -0500 Subject: [PATCH 47/47] mod_fifo: Explain session message unbridge constant --- src/mod/applications/mod_fifo/mod_fifo.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index fd25b3248f..48b02422aa 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1190,6 +1190,14 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ case SWITCH_MESSAGE_INDICATE_UNBRIDGE: if (msg->numeric_arg == 42) { /* See audio_bridge_thread() for source of 42 constant. */ + /* When a session is interrupted to execute an application + (e.g. by uuid_execute) we need to tell everything in FS + to unbridge the channel (e.g. to turn on the + jitterbuffer) but we need mod_fifo not to see the + unbridge because we don't want fifo to stop tracking + the call. So this magic number is a complete hack to + make this happen. So we ignore it here and simply fall + through. */ goto end; } if ((caller_session = switch_core_session_locate(msg->string_arg))) {