#include "asterisk.h"
#include "asterisk/astobj2.h"
#include "asterisk/strings.h"
#include "asterisk/ccss.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/event.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
Go to the source code of this file.
Data Structures | |
struct | ast_cc_config_params |
struct | ast_cc_monitor_failure_data |
struct | cc_agent_backend |
struct | cc_agent_backends |
struct | cc_callback_helper |
struct | cc_control_payload |
The payload for an AST_CONTROL_CC frame. More... | |
struct | cc_core_instance |
struct | cc_generic_agent_pvt |
struct | cc_monitor_backend |
struct | cc_monitor_backends |
struct | cc_monitor_tree |
The "tree" of interfaces that is dialed. More... | |
struct | cc_recall_ds_data |
struct | cc_state_change_args |
struct | cc_status_response_args |
struct | count_agents_cb_data |
struct | count_monitors_cb_data |
struct | dialed_cc_interfaces |
struct | extension_child_dialstring |
Data regarding an extension monitor's child's dialstrings. More... | |
struct | extension_monitor_pvt |
Private data for an extension monitor. More... | |
struct | generic_monitor_instance |
struct | generic_monitor_instance_list |
struct | generic_monitor_pvt |
private data for generic device monitor More... | |
struct | generic_tp_cb_data |
Defines | |
#define | CC_MAX_AGENTS_DEFAULT 5 |
#define | CC_MAX_MONITORS_DEFAULT 5 |
#define | CC_OFFER_TIMER_DEFAULT 20 |
#define | CC_RECALL_TIMER_DEFAULT 20 |
#define | CCBS_AVAILABLE_TIMER_DEFAULT 4800 |
#define | CCNR_AVAILABLE_TIMER_DEFAULT 7200 |
#define | GLOBAL_CC_MAX_REQUESTS_DEFAULT 20 |
Enumerations | |
enum | cc_state { CC_AVAILABLE, CC_CALLER_OFFERED, CC_CALLER_REQUESTED, CC_ACTIVE, CC_CALLEE_READY, CC_CALLER_BUSY, CC_RECALLING, CC_COMPLETE, CC_FAILED } |
The states used in the CCSS core state machine. More... | |
enum | match_flags { MATCH_NO_REQUEST = (1 << 0), MATCH_REQUEST = (1 << 1) } |
Functions | |
ast_cc_config_params * | __ast_cc_config_params_init (const char *file, int line, const char *function) |
Allocate and initialize an ast_cc_config_params structure. | |
static void | agent_destroy (void *data) |
static const char * | agent_policy_to_str (enum ast_cc_agent_policies policy) |
int | ast_cc_agent_accept_request (int core_id, const char *const debug,...) |
Accept inbound CC request. | |
ast_cc_agent * | ast_cc_agent_callback (int flags, ao2_callback_fn *function, void *args, const char *const type) |
Call a callback on all agents of a specific type. | |
int | ast_cc_agent_caller_available (int core_id, const char *const debug,...) |
Indicate that a previously unavailable caller has become available. | |
int | ast_cc_agent_caller_busy (int core_id, const char *debug,...) |
Indicate that the caller is busy. | |
int | ast_cc_agent_recalling (int core_id, const char *const debug,...) |
Tell the CC core that a caller is currently recalling. | |
int | ast_cc_agent_register (const struct ast_cc_agent_callbacks *callbacks) |
Register a set of agent callbacks with the core. | |
int | ast_cc_agent_set_interfaces_chanvar (struct ast_channel *chan) |
Set the first level CC_INTERFACES channel variable for a channel. | |
int | ast_cc_agent_status_response (int core_id, enum ast_device_state devstate) |
Response with a caller's current status. | |
void | ast_cc_agent_unregister (const struct ast_cc_agent_callbacks *callbacks) |
Unregister a set of agent callbacks with the core. | |
int | ast_cc_available_timer_expire (const void *data) |
Scheduler callback for available timer expiration. | |
int | ast_cc_build_frame (struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, enum ast_cc_service_type service, void *private_data, struct ast_frame *frame) |
Create a CC Control frame. | |
void | ast_cc_busy_interface (struct ast_channel *inbound, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, void *private_data) |
Callback made from ast_cc_callback for certain channel types. | |
void | ast_cc_call_failed (struct ast_channel *incoming, struct ast_channel *outgoing, const char *const dialstring) |
Make CCBS available in the case that ast_call fails. | |
int | ast_cc_call_init (struct ast_channel *chan, int *ignore_cc) |
Start the CC process on a call. | |
int | ast_cc_callback (struct ast_channel *inbound, const char *const tech, const char *const dest, ast_cc_callback_fn callback) |
Run a callback for potential matching destinations. | |
int | ast_cc_completed (struct ast_channel *chan, const char *const debug,...) |
Indicate recall has been acknowledged. | |
void | ast_cc_config_params_destroy (struct ast_cc_config_params *params) |
Free memory from CCSS configuration params. | |
void | ast_cc_copy_config_params (struct ast_cc_config_params *dest, const struct ast_cc_config_params *src) |
copy CCSS configuration parameters from one structure to another | |
void | ast_cc_default_config_params (struct ast_cc_config_params *params) |
Set the specified CC config params to default values. | |
void | ast_cc_extension_monitor_add_dialstring (struct ast_channel *incoming, const char *const dialstring, const char *const device_name) |
Add a child dialstring to an extension monitor. | |
int | ast_cc_failed (int core_id, const char *const debug,...) |
Indicate failure has occurred. | |
int | ast_cc_get_current_core_id (struct ast_channel *chan) |
Get the core id for the current call. | |
ast_cc_monitor * | ast_cc_get_monitor_by_recall_core_id (const int core_id, const char *const device_name) |
Get the associated monitor given the device name and core_id. | |
int | ast_cc_get_param (struct ast_cc_config_params *params, const char *const name, char *buf, size_t buf_len) |
get a CCSS configuration parameter, given its name | |
int | ast_cc_init (void) |
Initialize CCSS. | |
int | ast_cc_is_config_param (const char *const name) |
Is this a CCSS configuration parameter? | |
int | ast_cc_is_recall (struct ast_channel *chan, int *core_id, const char *const monitor_type) |
Decide if a call to a particular channel is a CC recall. | |
int | ast_cc_monitor_callee_available (const int core_id, const char *const debug,...) |
Alert the core that a device being monitored has become available. | |
int | ast_cc_monitor_count (const char *const name, const char *const type) |
Return the number of outstanding CC requests to a specific device. | |
int | ast_cc_monitor_failed (int core_id, const char *const monitor_name, const char *const debug,...) |
Indicate that a failure has occurred on a specific monitor. | |
int | ast_cc_monitor_party_b_free (int core_id) |
Alert a caller that though the callee has become free, the caller himself is not and may not call back. | |
int | ast_cc_monitor_register (const struct ast_cc_monitor_callbacks *callbacks) |
Register a set of monitor callbacks with the core. | |
int | ast_cc_monitor_request_acked (int core_id, const char *const debug,...) |
Indicate that an outbound entity has accepted our CC request. | |
int | ast_cc_monitor_status_request (int core_id) |
Request the status of a caller or callers. | |
int | ast_cc_monitor_stop_ringing (int core_id) |
Alert a caller to stop ringing. | |
void | ast_cc_monitor_unregister (const struct ast_cc_monitor_callbacks *callbacks) |
Unregister a set of monitor callbacks with the core. | |
int | ast_cc_offer (struct ast_channel *caller_chan) |
Offer CC to a caller. | |
int | ast_cc_request_is_within_limits (void) |
Check if the incoming CC request is within the bounds set by the cc_max_requests configuration option. | |
int | ast_cc_set_param (struct ast_cc_config_params *params, const char *const name, const char *const value) |
set a CCSS configuration parameter, given its name | |
const char * | ast_get_cc_agent_dialstring (struct ast_cc_config_params *config) |
Get the cc_agent_dialstring. | |
enum ast_cc_agent_policies | ast_get_cc_agent_policy (struct ast_cc_config_params *config) |
Get the cc_agent_policy. | |
const char * | ast_get_cc_callback_macro (struct ast_cc_config_params *config) |
Get the name of the callback_macro. | |
unsigned int | ast_get_cc_max_agents (struct ast_cc_config_params *config) |
Get the cc_max_agents. | |
unsigned int | ast_get_cc_max_monitors (struct ast_cc_config_params *config) |
Get the cc_max_monitors. | |
enum ast_cc_monitor_policies | ast_get_cc_monitor_policy (struct ast_cc_config_params *config) |
Get the cc_monitor_policy. | |
unsigned int | ast_get_cc_offer_timer (struct ast_cc_config_params *config) |
Get the cc_offer_timer. | |
unsigned int | ast_get_cc_recall_timer (struct ast_cc_config_params *config) |
Get the cc_recall_timer. | |
unsigned int | ast_get_ccbs_available_timer (struct ast_cc_config_params *config) |
Get the ccbs_available_timer. | |
unsigned int | ast_get_ccnr_available_timer (struct ast_cc_config_params *config) |
Get the ccnr_available_timer. | |
void | ast_handle_cc_control_frame (struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data) |
Properly react to a CC control frame. | |
void | ast_ignore_cc (struct ast_channel *chan) |
Mark the channel to ignore further CC activity. | |
int | ast_queue_cc_frame (struct ast_channel *chan, const char *monitor_type, const char *const dialstring, enum ast_cc_service_type service, void *private_data) |
Queue an AST_CONTROL_CC frame. | |
void | ast_set_cc_agent_dialstring (struct ast_cc_config_params *config, const char *const value) |
Set the cc_agent_dialstring. | |
int | ast_set_cc_agent_policy (struct ast_cc_config_params *config, enum ast_cc_agent_policies value) |
Set the cc_agent_policy. | |
void | ast_set_cc_callback_macro (struct ast_cc_config_params *config, const char *const value) |
Set the callback_macro name. | |
int | ast_set_cc_interfaces_chanvar (struct ast_channel *chan, const char *const extension) |
Set the CC_INTERFACES channel variable for a channel using an extension as a starting point. | |
void | ast_set_cc_max_agents (struct ast_cc_config_params *config, unsigned int value) |
Set the cc_max_agents. | |
void | ast_set_cc_max_monitors (struct ast_cc_config_params *config, unsigned int value) |
Set the cc_max_monitors. | |
int | ast_set_cc_monitor_policy (struct ast_cc_config_params *config, enum ast_cc_monitor_policies value) |
Set the cc_monitor_policy. | |
void | ast_set_cc_offer_timer (struct ast_cc_config_params *config, unsigned int value) |
Set the cc_offer_timer. | |
void | ast_set_cc_recall_timer (struct ast_cc_config_params *config, unsigned int value) |
Set the cc_recall_timer. | |
void | ast_set_ccbs_available_timer (struct ast_cc_config_params *config, unsigned int value) |
Set the ccbs_available_timer. | |
void | ast_set_ccnr_available_timer (struct ast_cc_config_params *config, unsigned int value) |
Set the ccnr_available_timer. | |
int | ast_setup_cc_recall_datastore (struct ast_channel *chan, const int core_id) |
Set up a CC recall datastore on a channel. | |
static void | build_cc_interfaces_chanvar (struct ast_cc_monitor *starting_point, struct ast_str *str) |
static void | call_destructor_with_no_monitor (const char *const monitor_type, void *private_data) |
static void | cancel_available_timer (struct cc_core_instance *core_instance) |
static int | cc_active (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_agent_callback_helper (void *obj, void *args, int flags) |
static struct ast_cc_agent * | cc_agent_init (struct ast_channel *caller_chan, const char *const caller_name, const int core_id, struct cc_monitor_tree *interface_tree) |
static int | cc_available (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_build_payload (struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *dialstring, enum ast_cc_service_type service, void *private_data, struct cc_control_payload *payload) |
static int | cc_callee_ready (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_caller_busy (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_caller_offered (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_caller_requested (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_cli_output_status (void *data) |
static void | cc_cli_print_monitor_stats (struct ast_cc_monitor *monitor, int fd, int parent_id) |
static int | cc_complete (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static struct cc_core_instance * | cc_core_init_instance (struct ast_channel *caller_chan, struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data) |
static int | cc_core_instance_cmp_fn (void *obj, void *arg, int flags) |
static void | cc_core_instance_destructor (void *data) |
static int | cc_core_instance_hash_fn (const void *obj, const int flags) |
static struct ast_cc_monitor * | cc_device_monitor_init (const char *const device_name, const char *const dialstring, const struct cc_control_payload *cc_data, int core_id) |
static int | cc_do_state_change (void *datap) |
static void | cc_extension_monitor_change_is_valid (struct cc_core_instance *core_instance, unsigned int parent_id, const char *const device_name, int is_valid) |
static void | cc_extension_monitor_destructor (void *private_data) |
static struct ast_cc_monitor * | cc_extension_monitor_init (const char *const exten, const char *const context, const unsigned int parent_id) |
static int | cc_failed (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static void | cc_generic_agent_destructor (struct ast_cc_agent *agent) |
static int | cc_generic_agent_init (struct ast_cc_agent *agent, struct ast_channel *chan) |
static int | cc_generic_agent_recall (struct ast_cc_agent *agent) |
static void | cc_generic_agent_respond (struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason) |
static int | cc_generic_agent_start_monitoring (struct ast_cc_agent *agent) |
static int | cc_generic_agent_start_offer_timer (struct ast_cc_agent *agent) |
static int | cc_generic_agent_status_request (struct ast_cc_agent *agent) |
static int | cc_generic_agent_stop_offer_timer (struct ast_cc_agent *agent) |
static int | cc_generic_agent_stop_ringing (struct ast_cc_agent *agent) |
static int | cc_generic_monitor_cancel_available_timer (struct ast_cc_monitor *monitor, int *sched_id) |
static void | cc_generic_monitor_destructor (void *private_data) |
static int | cc_generic_monitor_request_cc (struct ast_cc_monitor *monitor, int *available_timer_id) |
static int | cc_generic_monitor_suspend (struct ast_cc_monitor *monitor) |
static int | cc_generic_monitor_unsuspend (struct ast_cc_monitor *monitor) |
static void | cc_interface_destroy (void *data) |
static void | cc_interface_tree_destroy (void *data) |
static int | cc_interfaces_datastore_init (struct ast_channel *chan) |
static void | cc_monitor_destroy (void *data) |
static int | cc_monitor_failed (void *data) |
static int | cc_offer (const int core_id, const char *const debug,...) |
static int | cc_party_b_free (void *data) |
static void | cc_recall_ds_destroy (void *data) |
static void * | cc_recall_ds_duplicate (void *data) |
static int | cc_recalling (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static void * | cc_ref (void *obj, const char *debug) |
static int | cc_request_state_change (enum cc_state state, const int core_id, const char *debug, va_list ap) |
static const char * | cc_service_to_string (enum ast_cc_service_type service) |
static const char * | cc_state_to_string (enum cc_state state) |
static int | cc_status_request (void *data) |
static int | cc_status_response (void *data) |
static int | cc_stop_ringing (void *data) |
static void | cc_unique_append (struct ast_str *str, const char *dialstring) |
static void * | cc_unref (void *obj, const char *debug) |
static int | cccancel_exec (struct ast_channel *chan, const char *data) |
static int | ccreq_exec (struct ast_channel *chan, const char *data) |
static void | check_callback_sanity (const struct ast_cc_agent_callbacks *callbacks) |
static char * | complete_core_id (const char *line, const char *word, int pos, int state) |
static long | count_agents (const char *const caller, const int core_id_exception) |
static int | count_agents_cb (void *obj, void *arg, void *data, int flags) |
static int | count_monitors_cb (void *obj, void *arg, int flags) |
static struct generic_monitor_instance_list * | create_new_generic_list (struct ast_cc_monitor *monitor) |
static void | dialed_cc_interfaces_destroy (void *data) |
static void * | dialed_cc_interfaces_duplicate (void *data) |
static struct extension_monitor_pvt * | extension_monitor_pvt_init (void) |
static struct ast_cc_agent_callbacks * | find_agent_callbacks (struct ast_channel *chan) |
static struct cc_core_instance * | find_cc_core_instance (const int core_id) |
static struct generic_monitor_instance_list * | find_generic_monitor_instance_list (const char *const device_name) |
static struct ast_cc_monitor_callbacks * | find_monitor_callbacks (const char *const type) |
static void | generic_agent_devstate_cb (const struct ast_event *event, void *userdata) |
static int | generic_agent_devstate_unsubscribe (void *data) |
static int | generic_monitor_cmp_fn (void *obj, void *arg, int flags) |
static void | generic_monitor_devstate_cb (const struct ast_event *event, void *userdata) |
static int | generic_monitor_devstate_tp_cb (void *data) |
static int | generic_monitor_hash_fn (const void *obj, const int flags) |
static void | generic_monitor_instance_list_destructor (void *obj) |
static void * | generic_recall (void *data) |
static char * | handle_cc_kill (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cc_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | has_device_monitors (struct cc_core_instance *core_instance) |
check if the core instance has any device monitors | |
static void | initialize_cc_max_requests (void) |
static int | is_state_change_valid (enum cc_state current_state, const enum cc_state new_state, struct ast_cc_agent *agent) |
static int | kill_cores (void *obj, void *arg, int flags) |
static void | kill_duplicate_offers (char *caller) |
static int | match_agent (void *obj, void *arg, void *data, int flags) |
static const char * | monitor_policy_to_str (enum ast_cc_monitor_policies policy) |
static int | offer_timer_expire (const void *data) |
static int | print_stats_cb (void *obj, void *arg, int flags) |
static void | request_cc (struct cc_core_instance *core_instance) |
static enum ast_cc_agent_policies | str_to_agent_policy (const char *const value) |
static enum ast_cc_monitor_policies | str_to_monitor_policy (const char *const value) |
static void | suspend (struct cc_core_instance *core_instance) |
static void | unsuspend (struct cc_core_instance *core_instance) |
Variables | |
static struct ast_cli_entry | cc_cli [] |
static struct ao2_container * | cc_core_instances |
static const int | CC_CORE_INSTANCES_BUCKETS = 17 |
static struct ast_taskprocessor * | cc_core_taskprocessor |
static struct ast_cc_config_params | cc_default_params |
static int | cc_logger_level |
static const char * | CC_LOGGER_LEVEL_NAME = "CC" |
static int | cc_request_count |
static struct ast_sched_thread * | cc_sched_thread |
struct { | |
enum ast_cc_service_type service | |
const char * service_string | |
} | cc_service_to_string_map [] |
struct { | |
enum cc_state state | |
const char * state_string | |
} | cc_state_to_string_map [] |
static const char * | cccancel_app = "CallCompletionCancel" |
static const char * | ccreq_app = "CallCompletionRequest" |
static int | core_id_counter |
static int | dialed_cc_interface_counter |
static struct ast_datastore_info | dialed_cc_interfaces_info |
static struct ast_cc_agent_callbacks | generic_agent_callbacks |
static struct ast_cc_monitor_callbacks | generic_monitor_cbs |
ao2_container * | generic_monitors |
static unsigned int | global_cc_max_requests |
static struct ast_datastore_info | recall_ds_info |
static int(*const []) | state_change_funcs (struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state) |
Definition in file ccss.c.
#define GLOBAL_CC_MAX_REQUESTS_DEFAULT 20 |
enum cc_state |
The states used in the CCSS core state machine.
Definition at line 138 of file ccss.c.
00138 { 00139 /*! Entered when it is determined that CCSS may be used for the call */ 00140 CC_AVAILABLE, 00141 /*! Entered when a CCSS agent has offered CCSS to a caller */ 00142 CC_CALLER_OFFERED, 00143 /*! Entered when a CCSS agent confirms that a caller has 00144 * requested CCSS */ 00145 CC_CALLER_REQUESTED, 00146 /*! Entered when a CCSS monitor confirms acknowledgment of an 00147 * outbound CCSS request */ 00148 CC_ACTIVE, 00149 /*! Entered when a CCSS monitor alerts the core that the called party 00150 * has become available */ 00151 CC_CALLEE_READY, 00152 /*! Entered when a CCSS agent alerts the core that the calling party 00153 * may not be recalled because he is unavailable 00154 */ 00155 CC_CALLER_BUSY, 00156 /*! Entered when a CCSS agent alerts the core that the calling party 00157 * is attempting to recall the called party 00158 */ 00159 CC_RECALLING, 00160 /*! Entered when an application alerts the core that the calling party's 00161 * recall attempt has had a call progress response indicated 00162 */ 00163 CC_COMPLETE, 00164 /*! Entered any time that something goes wrong during the process, thus 00165 * resulting in the failure of the attempted CCSS transaction. Note also 00166 * that cancellations of CC are treated as failures. 00167 */ 00168 CC_FAILED, 00169 };
enum match_flags |
Definition at line 426 of file ccss.c.
00426 { 00427 /* Only match agents that have not yet 00428 * made a CC request 00429 */ 00430 MATCH_NO_REQUEST = (1 << 0), 00431 /* Only match agents that have made 00432 * a CC request 00433 */ 00434 MATCH_REQUEST = (1 << 1), 00435 };
struct ast_cc_config_params* __ast_cc_config_params_init | ( | const char * | file, | |
int | line, | |||
const char * | function | |||
) |
Allocate and initialize an ast_cc_config_params structure.
NULL | Unable to allocate the structure | |
non-NULL | A pointer to the newly allocated and initialized structure |
Definition at line 530 of file ccss.c.
References __ast_malloc(), ast_cc_default_config_params(), and ast_malloc.
00531 { 00532 #if defined(__AST_DEBUG_MALLOC) 00533 struct ast_cc_config_params *params = __ast_malloc(sizeof(*params), file, line, function); 00534 #else 00535 struct ast_cc_config_params *params = ast_malloc(sizeof(*params)); 00536 #endif 00537 00538 if (!params) { 00539 return NULL; 00540 } 00541 00542 ast_cc_default_config_params(params); 00543 return params; 00544 }
static void agent_destroy | ( | void * | data | ) | [static] |
Definition at line 2215 of file ccss.c.
References ast_cc_config_params_destroy(), ast_cc_agent::callbacks, ast_cc_agent::cc_params, and ast_cc_agent_callbacks::destructor.
Referenced by cc_agent_init().
02216 { 02217 struct ast_cc_agent *agent = data; 02218 02219 if (agent->callbacks) { 02220 agent->callbacks->destructor(agent); 02221 } 02222 ast_cc_config_params_destroy(agent->cc_params); 02223 }
static const char* agent_policy_to_str | ( | enum ast_cc_agent_policies | policy | ) | [static] |
Definition at line 581 of file ccss.c.
References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, and AST_CC_AGENT_NEVER.
Referenced by ast_cc_get_param().
00582 { 00583 switch (policy) { 00584 case AST_CC_AGENT_NEVER: 00585 return "never"; 00586 case AST_CC_AGENT_NATIVE: 00587 return "native"; 00588 case AST_CC_AGENT_GENERIC: 00589 return "generic"; 00590 default: 00591 /* This should never happen... */ 00592 return ""; 00593 } 00594 }
int ast_cc_agent_accept_request | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Accept inbound CC request.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3431 of file ccss.c.
References CC_CALLER_REQUESTED, and cc_request_state_change().
Referenced by ccreq_exec(), handle_cc_subscribe(), and sig_pri_handle_cis_subcmds().
03432 { 03433 va_list ap; 03434 int res; 03435 03436 va_start(ap, debug); 03437 res = cc_request_state_change(CC_CALLER_REQUESTED, core_id, debug, ap); 03438 va_end(ap); 03439 return res; 03440 }
struct ast_cc_agent* ast_cc_agent_callback | ( | int | flags, | |
ao2_callback_fn * | function, | |||
void * | arg, | |||
const char *const | type | |||
) |
Call a callback on all agents of a specific type.
Since the container of CC core instances is private, and so are the items which the container contains, we have to provide an ao2_callback-like method so that a specific agent may be found or so that an operation can be made on all agents of a particular type. The first three arguments should be familiar to anyone who has used ao2_callback. The final argument is the type of agent you wish to have the callback called on.
flags | astobj2 search flags | |
function | an ao2 callback function to call | |
arg | the argument to the callback function | |
type | The type of agents to call the callback on |
Definition at line 413 of file ccss.c.
References cc_core_instance::agent, ao2_t_callback, cc_agent_callback_helper(), cc_core_instances, cc_ref(), cc_unref(), and cc_callback_helper::function.
Referenced by find_sip_cc_agent_by_notify_uri(), find_sip_cc_agent_by_original_callid(), and find_sip_cc_agent_by_subscribe_uri().
00414 { 00415 struct cc_callback_helper helper = {.function = function, .args = args, .type = type}; 00416 struct cc_core_instance *core_instance; 00417 if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper, 00418 "Calling provided agent callback function"))) { 00419 struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent"); 00420 cc_unref(core_instance, "agent callback done with the core_instance"); 00421 return agent; 00422 } 00423 return NULL; 00424 }
int ast_cc_agent_caller_available | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate that a previously unavailable caller has become available.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3475 of file ccss.c.
References CC_ACTIVE, and cc_request_state_change().
Referenced by cc_esc_publish_handler(), generic_agent_devstate_cb(), and sig_pri_handle_cis_subcmds().
03476 { 03477 va_list ap; 03478 int res; 03479 03480 va_start(ap, debug); 03481 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap); 03482 va_end(ap); 03483 return res; 03484 }
int ast_cc_agent_caller_busy | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate that the caller is busy.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3464 of file ccss.c.
References CC_CALLER_BUSY, and cc_request_state_change().
Referenced by cc_esc_publish_handler(), cc_generic_agent_recall(), sig_pri_handle_cis_subcmds(), and sip_cc_agent_recall().
03465 { 03466 va_list ap; 03467 int res; 03468 03469 va_start(ap, debug); 03470 res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap); 03471 va_end(ap); 03472 return res; 03473 }
int ast_cc_agent_recalling | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Tell the CC core that a caller is currently recalling.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3486 of file ccss.c.
References CC_RECALLING, and cc_request_state_change().
Referenced by generic_recall(), get_destination(), and sig_pri_handle_subcmds().
03487 { 03488 va_list ap; 03489 int res; 03490 03491 va_start(ap, debug); 03492 res = cc_request_state_change(CC_RECALLING, core_id, debug, ap); 03493 va_end(ap); 03494 return res; 03495 }
int ast_cc_agent_register | ( | const struct ast_cc_agent_callbacks * | callbacks | ) |
Register a set of agent callbacks with the core.
callbacks | The callbacks used by the agent implementation |
0 | Successfully registered | |
-1 | Failure to register |
Definition at line 917 of file ccss.c.
References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and cc_monitor_backend::next.
Referenced by ast_cc_init(), and load_module().
00918 { 00919 struct cc_agent_backend *backend = ast_calloc(1, sizeof(*backend)); 00920 00921 if (!backend) { 00922 return -1; 00923 } 00924 00925 backend->callbacks = callbacks; 00926 AST_RWLIST_WRLOCK(&cc_agent_backends); 00927 AST_RWLIST_INSERT_TAIL(&cc_agent_backends, backend, next); 00928 AST_RWLIST_UNLOCK(&cc_agent_backends); 00929 return 0; 00930 }
int ast_cc_agent_set_interfaces_chanvar | ( | struct ast_channel * | chan | ) |
Set the first level CC_INTERFACES channel variable for a channel.
This function will lock the channel as well as the list of monitors stored on the channel's CC recall datastore, though neither are held at the same time. Callers of this function should be aware of potential lock ordering problems that may arise.
chan | The channel to set the CC_INTERFACES variable on |
Definition at line 3286 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_free, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_str_buffer(), ast_str_create(), build_cc_interfaces_chanvar(), cc_recall_ds_data::core_id, ast_datastore::data, cc_recall_ds_data::interface_tree, monitor, pbx_builtin_setvar_helper(), recall_ds_info, and str.
Referenced by generic_recall(), handle_request_invite(), and sig_pri_handle_subcmds().
03287 { 03288 struct ast_datastore *recall_datastore; 03289 struct cc_monitor_tree *interface_tree; 03290 struct ast_cc_monitor *monitor; 03291 struct cc_recall_ds_data *recall_data; 03292 struct ast_str *str = ast_str_create(64); 03293 int core_id; 03294 03295 if (!str) { 03296 return -1; 03297 } 03298 03299 ast_channel_lock(chan); 03300 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03301 ast_channel_unlock(chan); 03302 ast_free(str); 03303 return -1; 03304 } 03305 recall_data = recall_datastore->data; 03306 interface_tree = recall_data->interface_tree; 03307 core_id = recall_data->core_id; 03308 ast_channel_unlock(chan); 03309 03310 AST_LIST_LOCK(interface_tree); 03311 monitor = AST_LIST_FIRST(interface_tree); 03312 build_cc_interfaces_chanvar(monitor, str); 03313 AST_LIST_UNLOCK(interface_tree); 03314 03315 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str)); 03316 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n", 03317 core_id, ast_str_buffer(str)); 03318 03319 ast_free(str); 03320 return 0; 03321 }
int ast_cc_agent_status_response | ( | int | core_id, | |
enum ast_device_state | devstate | |||
) |
Response with a caller's current status.
When an ISDN PTMP monitor requests the caller's status, the agent must respond to the request using this function. For simplicity it is recommended that the devstate parameter be one of AST_DEVICE_INUSE or AST_DEVICE_NOT_INUSE.
core_id | The core ID of the CC transaction | |
devstate | The current state of the caller to which the agent pertains |
0 | Successfully responded with our status | |
-1 | Failed to respond with our status |
Definition at line 3751 of file ccss.c.
References args, ast_calloc, ast_free, ast_taskprocessor_push(), cc_core_taskprocessor, cc_status_response(), cc_unref(), and find_cc_core_instance().
Referenced by cc_generic_agent_status_request(), sig_pri_handle_cis_subcmds(), and sip_cc_agent_status_request().
03752 { 03753 struct cc_status_response_args *args; 03754 struct cc_core_instance *core_instance; 03755 int res; 03756 03757 args = ast_calloc(1, sizeof(*args)); 03758 if (!args) { 03759 return -1; 03760 } 03761 03762 core_instance = find_cc_core_instance(core_id); 03763 if (!core_instance) { 03764 ast_free(args); 03765 return -1; 03766 } 03767 03768 args->core_instance = core_instance; 03769 args->devstate = devstate; 03770 03771 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_response, args); 03772 if (res) { 03773 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03774 ast_free(args); 03775 } 03776 return res; 03777 }
void ast_cc_agent_unregister | ( | const struct ast_cc_agent_callbacks * | callbacks | ) |
Unregister a set of agent callbacks with the core.
callbacks | The callbacks used by the agent implementation |
0 | Successfully unregistered | |
-1 | Failure to unregister |
Definition at line 932 of file ccss.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cc_monitor_backend::callbacks, cc_agent_backend::callbacks, and cc_monitor_backend::next.
Referenced by __unload_module(), and unload_module().
00933 { 00934 struct cc_agent_backend *backend; 00935 AST_RWLIST_WRLOCK(&cc_agent_backends); 00936 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_agent_backends, backend, next) { 00937 if (backend->callbacks == callbacks) { 00938 AST_RWLIST_REMOVE_CURRENT(next); 00939 ast_free(backend); 00940 break; 00941 } 00942 } 00943 AST_RWLIST_TRAVERSE_SAFE_END; 00944 AST_RWLIST_UNLOCK(&cc_agent_backends); 00945 }
int ast_cc_available_timer_expire | ( | const void * | data | ) |
Scheduler callback for available timer expiration.
data | A reference to the CC monitor on which the timer was running. |
Definition at line 1184 of file ccss.c.
References ast_cc_monitor_failed(), cc_unref(), and monitor.
Referenced by cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().
01185 { 01186 struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data; 01187 int res; 01188 monitor->available_timer_id = -1; 01189 res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor"); 01190 cc_unref(monitor, "Unref reference from scheduler\n"); 01191 return res; 01192 }
int ast_cc_build_frame | ( | struct ast_channel * | chan, | |
struct ast_cc_config_params * | cc_params, | |||
const char * | monitor_type, | |||
const char *const | device_name, | |||
const char *const | dialstring, | |||
enum ast_cc_service_type | service, | |||
void * | private_data, | |||
struct ast_frame * | frame | |||
) |
Create a CC Control frame.
chan | A channel involved in the call. What we want is on a datastore on both incoming and outgoing so either may be provided | |
cc_params | The CC configuration parameters for the outbound target | |
monitor_type | The type of monitor to use when CC is requested | |
device_name | The name of the outbound target device. | |
dialstring | The dial string used when calling this specific interface | |
service | What kind of CC service is being offered. (CCBS/CCNR/etc...) | |
private_data | If a native monitor is being used, and some channel-driver-specific private data has been allocated, then this parameter should contain a pointer to that data. If using a generic monitor, this parameter should remain NULL. Note that if this function should fail at some point, it is the responsibility of the caller to free the private data upon return. | |
[out] | frame | The frame we will be returning to the caller. It is vital that ast_frame_free be called on this frame since the payload will be allocated on the heap. |
-1 | Failure. At some point there was a failure. Do not attempt to use the frame in this case. | |
0 | Success |
Definition at line 3834 of file ccss.c.
References ast_calloc, AST_CONTROL_CC, AST_FRAME_CONTROL, ast_free, AST_MALLOCD_DATA, cc_build_payload(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, ast_frame::ptr, and ast_frame::subclass.
Referenced by ast_queue_cc_frame().
03838 { 03839 struct cc_control_payload *payload = ast_calloc(1, sizeof(*payload)); 03840 03841 if (!payload) { 03842 return -1; 03843 } 03844 if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) { 03845 /* Something screwed up, we can't make a frame with this */ 03846 ast_free(payload); 03847 return -1; 03848 } 03849 frame->frametype = AST_FRAME_CONTROL; 03850 frame->subclass.integer = AST_CONTROL_CC; 03851 frame->data.ptr = payload; 03852 frame->datalen = sizeof(*payload); 03853 frame->mallocd = AST_MALLOCD_DATA; 03854 return 0; 03855 }
void ast_cc_busy_interface | ( | struct ast_channel * | inbound, | |
struct ast_cc_config_params * | cc_params, | |||
const char * | monitor_type, | |||
const char *const | device_name, | |||
const char *const | dialstring, | |||
void * | private_data | |||
) |
Callback made from ast_cc_callback for certain channel types.
inbound | Incoming asterisk channel. | |
cc_params | The CC configuration parameters for the outbound target | |
monitor_type | The type of monitor to use when CC is requested | |
device_name | The name of the outbound target device. | |
dialstring | The dial string used when calling this specific interface | |
private_data | If a native monitor is being used, and some channel-driver-specific private data has been allocated, then this parameter should contain a pointer to that data. If using a generic monitor, this parameter should remain NULL. Note that if this function should fail at some point, it is the responsibility of the caller to free the private data upon return. |
This function creates a CC control frame payload, simulating the act of reading it from the nonexistent outgoing channel's frame queue. We then handle this simulated frame just as we would a normal CC frame which had actually been queued by the channel driver.
Definition at line 3890 of file ccss.c.
References AST_CC_CCBS, ast_handle_cc_control_frame(), call_destructor_with_no_monitor(), and cc_build_payload().
Referenced by dial_exec_full().
03892 { 03893 struct cc_control_payload payload; 03894 if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) { 03895 /* Something screwed up. Don't try to handle this payload */ 03896 call_destructor_with_no_monitor(monitor_type, private_data); 03897 return; 03898 } 03899 ast_handle_cc_control_frame(inbound, NULL, &payload); 03900 }
void ast_cc_call_failed | ( | struct ast_channel * | incoming, | |
struct ast_channel * | outgoing, | |||
const char *const | dialstring | |||
) |
Make CCBS available in the case that ast_call fails.
One caveat is that this may only be used if generic monitoring is being used. The reason is that since Asterisk determined that the device was busy without actually placing a call to it, the far end will have no idea what call we are requesting call completion for if we were to send a call completion request.
Definition at line 3857 of file ccss.c.
References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CC_CCBS, AST_CC_GENERIC_MONITOR_TYPE, AST_CC_MONITOR_GENERIC, ast_channel_get_cc_config_params(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_get_cc_monitor_policy(), ast_handle_cc_control_frame(), cc_build_payload(), and ast_channel::hangupcause.
Referenced by dial_exec_full().
03858 { 03859 char device_name[AST_CHANNEL_NAME]; 03860 struct cc_control_payload payload; 03861 struct ast_cc_config_params *cc_params; 03862 03863 if (outgoing->hangupcause != AST_CAUSE_BUSY && outgoing->hangupcause != AST_CAUSE_CONGESTION) { 03864 /* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call 03865 * failing is something other than busy or congestion 03866 */ 03867 return; 03868 } 03869 03870 cc_params = ast_channel_get_cc_config_params(outgoing); 03871 if (!cc_params) { 03872 return; 03873 } 03874 if (ast_get_cc_monitor_policy(cc_params) != AST_CC_MONITOR_GENERIC) { 03875 /* This sort of CCBS only works if using generic CC. For native, we would end up sending 03876 * a CC request for a non-existent call. The far end will reject this every time 03877 */ 03878 return; 03879 } 03880 03881 ast_channel_get_device_name(outgoing, device_name, sizeof(device_name)); 03882 if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name, 03883 dialstring, AST_CC_CCBS, NULL, &payload)) { 03884 /* Something screwed up, we can't make a frame with this */ 03885 return; 03886 } 03887 ast_handle_cc_control_frame(incoming, outgoing, &payload); 03888 }
int ast_cc_call_init | ( | struct ast_channel * | chan, | |
int * | ignore_cc | |||
) |
Start the CC process on a call.
The ignore_cc parameter is a convenience parameter. It can save an application the trouble of trying to call CC APIs when it knows that it should just ignore further attempts at CC actions.
chan | The inbound channel calling the CC-capable application. | |
[out] | ignore_cc | Will be set non-zero if no further CC actions need to be taken |
0 | Success | |
-1 | Failure |
Definition at line 2091 of file ccss.c.
References AST_CC_AGENT_NEVER, ast_channel_datastore_find(), ast_channel_get_cc_config_params(), ast_channel_lock, ast_channel_unlock, ast_get_cc_agent_policy(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log_dynamic_level, cc_extension_monitor_init(), cc_interfaces_datastore_init(), cc_ref(), cc_unref(), ast_channel::context, dialed_cc_interfaces::core_id, ast_datastore::data, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces_info, ast_channel::exten, dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, ast_channel::macrocontext, ast_channel::macroexten, monitor, ast_channel::name, cc_monitor_backend::next, and S_OR.
Referenced by dial_exec_full().
02092 { 02093 /* There are three situations to deal with here: 02094 * 02095 * 1. The channel does not have a dialed_cc_interfaces datastore on 02096 * it. This means that this is the first time that Dial has 02097 * been called. We need to create/initialize the datastore. 02098 * 02099 * 2. The channel does have a cc_interface datastore on it and 02100 * the "ignore" indicator is 0. This means that a Local channel 02101 * was called by a "parent" dial. We can check the datastore's 02102 * parent field to see who the root of this particular dial tree 02103 * is. 02104 * 02105 * 3. The channel does have a cc_interface datastore on it and 02106 * the "ignore" indicator is 1. This means that a second Dial call 02107 * is being made from an extension. In this case, we do not 02108 * want to make any additions/modifications to the datastore. We 02109 * will instead set a flag to indicate that CCSS is completely 02110 * disabled for this Dial attempt. 02111 */ 02112 02113 struct ast_datastore *cc_interfaces_datastore; 02114 struct dialed_cc_interfaces *interfaces; 02115 struct ast_cc_monitor *monitor; 02116 struct ast_cc_config_params *cc_params; 02117 02118 ast_channel_lock(chan); 02119 02120 cc_params = ast_channel_get_cc_config_params(chan); 02121 if (!cc_params) { 02122 ast_channel_unlock(chan); 02123 return -1; 02124 } 02125 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) { 02126 /* We can't offer CC to this caller anyway, so don't bother with CC on this call 02127 */ 02128 *ignore_cc = 1; 02129 ast_channel_unlock(chan); 02130 ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", chan->name); 02131 return 0; 02132 } 02133 02134 if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) { 02135 /* Situation 1 has occurred */ 02136 ast_channel_unlock(chan); 02137 return cc_interfaces_datastore_init(chan); 02138 } 02139 interfaces = cc_interfaces_datastore->data; 02140 ast_channel_unlock(chan); 02141 02142 if (interfaces->ignore) { 02143 /* Situation 3 has occurred */ 02144 *ignore_cc = 1; 02145 ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n"); 02146 return 0; 02147 } 02148 02149 /* Situation 2 has occurred */ 02150 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten), 02151 S_OR(chan->macrocontext, chan->context), interfaces->dial_parent_id))) { 02152 return -1; 02153 } 02154 monitor->core_id = interfaces->core_id; 02155 AST_LIST_LOCK(interfaces->interface_tree); 02156 cc_ref(monitor, "monitor tree's reference to the monitor"); 02157 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next); 02158 AST_LIST_UNLOCK(interfaces->interface_tree); 02159 interfaces->dial_parent_id = monitor->id; 02160 cc_unref(monitor, "Unref monitor's allocation reference"); 02161 return 0; 02162 }
int ast_cc_callback | ( | struct ast_channel * | inbound, | |
const char *const | tech, | |||
const char *const | dest, | |||
ast_cc_callback_fn | callback | |||
) |
Run a callback for potential matching destinations.
inbound | ||
tech | Channel technology to use | |
dest | Channel/group/peer or whatever the specific technology uses | |
callback | Function to call when a target is reached |
Always | 0, I guess. |
Definition at line 3902 of file ccss.c.
References ast_get_channel_tech(), and ast_channel_tech::cc_callback.
Referenced by dial_exec_full().
03903 { 03904 const struct ast_channel_tech *chantech = ast_get_channel_tech(tech); 03905 03906 if (chantech && chantech->cc_callback) { 03907 chantech->cc_callback(inbound, dest, callback); 03908 } 03909 03910 return 0; 03911 }
int ast_cc_completed | ( | struct ast_channel * | chan, | |
const char *const | debug, | |||
... | ||||
) |
Indicate recall has been acknowledged.
chan | The inbound channel making the CC recall | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3497 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, CC_COMPLETE, cc_request_state_change(), cc_recall_ds_data::core_id, ast_datastore::data, cc_recall_ds_data::ignore, cc_recall_ds_data::nested, and recall_ds_info.
03498 { 03499 struct ast_datastore *recall_datastore; 03500 struct cc_recall_ds_data *recall_data; 03501 int core_id; 03502 va_list ap; 03503 int res; 03504 03505 ast_channel_lock(chan); 03506 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03507 /* Silly! Why did you call this function if there's no recall DS? */ 03508 ast_channel_unlock(chan); 03509 return -1; 03510 } 03511 recall_data = recall_datastore->data; 03512 if (recall_data->nested || recall_data->ignore) { 03513 /* If this is being called from a nested Dial, it is too 03514 * early to determine if the recall has actually completed. 03515 * The outermost dial is the only one with the authority to 03516 * declare the recall to be complete. 03517 * 03518 * Similarly, if this function has been called when the 03519 * recall has progressed beyond the first dial, this is not 03520 * a legitimate time to declare the recall to be done. In fact, 03521 * that should have been done already. 03522 */ 03523 ast_channel_unlock(chan); 03524 return -1; 03525 } 03526 core_id = recall_data->core_id; 03527 ast_channel_unlock(chan); 03528 va_start(ap, debug); 03529 res = cc_request_state_change(CC_COMPLETE, core_id, debug, ap); 03530 va_end(ap); 03531 return res; 03532 }
void ast_cc_config_params_destroy | ( | struct ast_cc_config_params * | params | ) |
Free memory from CCSS configuration params.
params | Pointer to structure whose memory we need to free |
void |
Definition at line 546 of file ccss.c.
References ast_free.
Referenced by __sip_destroy(), agent_destroy(), ast_channel_cc_params_init(), cc_interface_destroy(), channel_cc_params_destroy(), destroy_dahdi_pvt(), setup_dahdi(), and sip_destroy_peer().
00547 { 00548 ast_free(params); 00549 }
void ast_cc_copy_config_params | ( | struct ast_cc_config_params * | dest, | |
const struct ast_cc_config_params * | src | |||
) |
copy CCSS configuration parameters from one structure to another
src | The structure from which data is copied | |
dest | The structure to which data is copied |
Definition at line 708 of file ccss.c.
Referenced by ast_channel_cc_params_init(), cc_agent_init(), cc_build_payload(), cc_device_monitor_init(), channel_cc_params_copy(), check_peer_ok(), create_addr_from_peer(), dahdi_new(), deep_copy_dahdi_chan_conf(), and duplicate_pseudo().
void ast_cc_default_config_params | ( | struct ast_cc_config_params * | params | ) |
Set the specified CC config params to default values.
params | CC config params to set to default values. |
Definition at line 525 of file ccss.c.
References cc_default_params.
Referenced by __ast_cc_config_params_init().
00526 { 00527 *params = cc_default_params; 00528 }
void ast_cc_extension_monitor_add_dialstring | ( | struct ast_channel * | incoming, | |
const char *const | dialstring, | |||
const char *const | device_name | |||
) |
Add a child dialstring to an extension monitor.
incoming | The caller's channel | |
dialstring | The dialstring used when requesting the outbound channel | |
device_name | The device name associated with the requested outbound channel |
void |
Definition at line 1680 of file ccss.c.
References ast_calloc, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, extension_monitor_pvt::child_dialstrings, ast_datastore::data, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces_info, id, dialed_cc_interfaces::interface_tree, monitor, and cc_monitor_backend::next.
Referenced by dial_exec_full().
01681 { 01682 struct ast_datastore *cc_datastore; 01683 struct dialed_cc_interfaces *cc_interfaces; 01684 struct ast_cc_monitor *monitor; 01685 struct extension_monitor_pvt *extension_pvt; 01686 struct extension_child_dialstring *child_dialstring; 01687 struct cc_monitor_tree *interface_tree; 01688 int id; 01689 01690 ast_channel_lock(incoming); 01691 if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) { 01692 ast_channel_unlock(incoming); 01693 return; 01694 } 01695 01696 cc_interfaces = cc_datastore->data; 01697 interface_tree = cc_interfaces->interface_tree; 01698 id = cc_interfaces->dial_parent_id; 01699 ast_channel_unlock(incoming); 01700 01701 AST_LIST_LOCK(interface_tree); 01702 AST_LIST_TRAVERSE(interface_tree, monitor, next) { 01703 if (monitor->id == id) { 01704 break; 01705 } 01706 } 01707 01708 if (!monitor) { 01709 AST_LIST_UNLOCK(interface_tree); 01710 return; 01711 } 01712 01713 extension_pvt = monitor->private_data; 01714 if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) { 01715 AST_LIST_UNLOCK(interface_tree); 01716 return; 01717 } 01718 ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring)); 01719 ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name)); 01720 child_dialstring->is_valid = 1; 01721 AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next); 01722 AST_LIST_UNLOCK(interface_tree); 01723 }
int ast_cc_failed | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate failure has occurred.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3534 of file ccss.c.
References CC_FAILED, and cc_request_state_change().
Referenced by cancel_available_timer(), cc_caller_offered(), cc_caller_requested(), cc_monitor_failed(), cccancel_exec(), ccreq_exec(), generic_recall(), handle_cc_subscribe(), kill_cores(), offer_timer_expire(), request_cc(), sig_pri_handle_cis_subcmds(), sip_offer_timer_expire(), suspend(), unsuspend(), and wait_for_answer().
03535 { 03536 va_list ap; 03537 int res; 03538 03539 va_start(ap, debug); 03540 res = cc_request_state_change(CC_FAILED, core_id, debug, ap); 03541 va_end(ap); 03542 return res; 03543 }
int ast_cc_get_current_core_id | ( | struct ast_channel * | chan | ) |
Get the core id for the current call.
The channel given to this function may be an inbound or outbound channel. Both will have the necessary info on it.
chan | The channel from which to get the core_id. |
core_id | on success | |
-1 | Failure |
Definition at line 2169 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, dialed_cc_interfaces::core_id, ast_datastore::data, dialed_cc_interfaces_info, and dialed_cc_interfaces::ignore.
Referenced by sig_pri_cc_generic_check(), and sip_handle_cc().
02170 { 02171 struct ast_datastore *datastore; 02172 struct dialed_cc_interfaces *cc_interfaces; 02173 int core_id_return; 02174 02175 ast_channel_lock(chan); 02176 if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) { 02177 ast_channel_unlock(chan); 02178 return -1; 02179 } 02180 02181 cc_interfaces = datastore->data; 02182 core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id; 02183 ast_channel_unlock(chan); 02184 return core_id_return; 02185 02186 }
struct ast_cc_monitor* ast_cc_get_monitor_by_recall_core_id | ( | const int | core_id, | |
const char *const | device_name | |||
) |
Get the associated monitor given the device name and core_id.
core_id | The core ID to which this recall corresponds. This likely will have been obtained using the ast_cc_is_recall function | |
device_name | Which device to find the monitor for. |
NULL | Appropriate monitor does not exist | |
non-NULL | The monitor to use for this recall |
Definition at line 3174 of file ccss.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, cc_ref(), cc_unref(), ast_cc_interface::device_name, find_cc_core_instance(), ast_cc_monitor::interface, cc_core_instance::monitors, and cc_monitor_backend::next.
Referenced by sig_pri_call(), sig_pri_cc_generic_check(), and sip_call().
03175 { 03176 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03177 struct ast_cc_monitor *monitor_iter; 03178 03179 if (!core_instance) { 03180 return NULL; 03181 } 03182 03183 AST_LIST_LOCK(core_instance->monitors); 03184 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 03185 if (!strcmp(monitor_iter->interface->device_name, device_name)) { 03186 /* Found a monitor. */ 03187 cc_ref(monitor_iter, "Hand the requester of the monitor a reference"); 03188 break; 03189 } 03190 } 03191 AST_LIST_UNLOCK(core_instance->monitors); 03192 cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id"); 03193 return monitor_iter; 03194 }
int ast_cc_get_param | ( | struct ast_cc_config_params * | params, | |
const char *const | name, | |||
char * | buf, | |||
size_t | buf_len | |||
) |
get a CCSS configuration parameter, given its name
params | The CCSS configuration from which to get the value | |
name | The name of the CCSS parameter we want | |
buf | A preallocated buffer to hold the value | |
buf_len | The size of buf |
0 | Success | |
-1 | Failure |
Definition at line 612 of file ccss.c.
References agent_policy_to_str(), ast_copy_string(), ast_get_cc_agent_dialstring(), ast_get_cc_agent_policy(), ast_get_cc_callback_macro(), ast_get_cc_max_agents(), ast_get_cc_max_monitors(), ast_get_cc_monitor_policy(), ast_get_cc_offer_timer(), ast_get_cc_recall_timer(), ast_get_ccbs_available_timer(), ast_get_ccnr_available_timer(), ast_log(), LOG_WARNING, monitor_policy_to_str(), and value.
Referenced by acf_cc_read().
00614 { 00615 const char *value = NULL; 00616 00617 if (!strcasecmp(name, "cc_callback_macro")) { 00618 value = ast_get_cc_callback_macro(params); 00619 } else if (!strcasecmp(name, "cc_agent_policy")) { 00620 value = agent_policy_to_str(ast_get_cc_agent_policy(params)); 00621 } else if (!strcasecmp(name, "cc_monitor_policy")) { 00622 value = monitor_policy_to_str(ast_get_cc_monitor_policy(params)); 00623 } else if (!strcasecmp(name, "cc_agent_dialstring")) { 00624 value = ast_get_cc_agent_dialstring(params); 00625 } 00626 if (value) { 00627 ast_copy_string(buf, value, buf_len); 00628 return 0; 00629 } 00630 00631 /* The rest of these are all ints of some sort and require some 00632 * snprintf-itude 00633 */ 00634 00635 if (!strcasecmp(name, "cc_offer_timer")) { 00636 snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params)); 00637 } else if (!strcasecmp(name, "ccnr_available_timer")) { 00638 snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params)); 00639 } else if (!strcasecmp(name, "ccbs_available_timer")) { 00640 snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params)); 00641 } else if (!strcasecmp(name, "cc_max_agents")) { 00642 snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params)); 00643 } else if (!strcasecmp(name, "cc_max_monitors")) { 00644 snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params)); 00645 } else if (!strcasecmp(name, "cc_recall_timer")) { 00646 snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params)); 00647 } else { 00648 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name); 00649 return -1; 00650 } 00651 00652 return 0; 00653 }
int ast_cc_init | ( | void | ) |
Initialize CCSS.
0 | Success | |
nonzero | Failure |
Definition at line 4218 of file ccss.c.
References ao2_t_container_alloc, ARRAY_LEN, ast_cc_agent_register(), ast_cc_monitor_register(), ast_cli_register_multiple(), ast_logger_register_level(), ast_register_application2(), ast_sched_thread_create(), ast_taskprocessor_get(), cc_cli, cc_core_instance_cmp_fn(), cc_core_instance_hash_fn(), cc_core_instances, cc_core_taskprocessor, cc_sched_thread, cccancel_exec(), ccreq_exec(), generic_agent_callbacks, generic_monitor_cbs, generic_monitor_cmp_fn(), generic_monitor_hash_fn(), generic_monitors, initialize_cc_max_requests(), and TPS_REF_DEFAULT.
Referenced by main().
04219 { 04220 int res; 04221 04222 if (!(cc_core_instances = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS, 04223 cc_core_instance_hash_fn, cc_core_instance_cmp_fn, 04224 "Create core instance container"))) { 04225 return -1; 04226 } 04227 if (!(generic_monitors = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS, 04228 generic_monitor_hash_fn, generic_monitor_cmp_fn, 04229 "Create generic monitor container"))) { 04230 return -1; 04231 } 04232 if (!(cc_core_taskprocessor = ast_taskprocessor_get("CCSS core", TPS_REF_DEFAULT))) { 04233 return -1; 04234 } 04235 if (!(cc_sched_thread = ast_sched_thread_create())) { 04236 return -1; 04237 } 04238 res = ast_register_application2(ccreq_app, ccreq_exec, NULL, NULL, NULL); 04239 res |= ast_register_application2(cccancel_app, cccancel_exec, NULL, NULL, NULL); 04240 res |= ast_cc_monitor_register(&generic_monitor_cbs); 04241 res |= ast_cc_agent_register(&generic_agent_callbacks); 04242 ast_cli_register_multiple(cc_cli, ARRAY_LEN(cc_cli)); 04243 cc_logger_level = ast_logger_register_level(CC_LOGGER_LEVEL_NAME); 04244 dialed_cc_interface_counter = 1; 04245 initialize_cc_max_requests(); 04246 return res; 04247 }
int ast_cc_is_config_param | ( | const char *const | name | ) |
Is this a CCSS configuration parameter?
name | Name of configuration option being parsed. |
1 | Yes, this is a CCSS configuration parameter. | |
0 | No, this is not a CCSS configuration parameter. |
Definition at line 694 of file ccss.c.
Referenced by build_peer().
00695 { 00696 return (!strcasecmp(name, "cc_agent_policy") || 00697 !strcasecmp(name, "cc_monitor_policy") || 00698 !strcasecmp(name, "cc_offer_timer") || 00699 !strcasecmp(name, "ccnr_available_timer") || 00700 !strcasecmp(name, "ccbs_available_timer") || 00701 !strcasecmp(name, "cc_max_agents") || 00702 !strcasecmp(name, "cc_max_monitors") || 00703 !strcasecmp(name, "cc_callback_macro") || 00704 !strcasecmp(name, "cc_agent_dialstring") || 00705 !strcasecmp(name, "cc_recall_timer")); 00706 }
int ast_cc_is_recall | ( | struct ast_channel * | chan, | |
int * | core_id, | |||
const char *const | monitor_type | |||
) |
Decide if a call to a particular channel is a CC recall.
As a quick example, let's say a call is placed to SIP/1000 and SIP/1000 is currently on the phone. The caller requests CCBS. SIP/1000 finishes his call, and so the caller attempts to recall. Now, the dialplan administrator has set up this second call so that not only is SIP/1000 called, but also SIP/2000 is called. If SIP/1000's channel were passed to this function, the return value would be non-zero, but if SIP/2000's channel were passed into this function, then the return would be 0 since SIP/2000 was not one of the original devices dialed.
This function will lock the channel as well as the list of monitors on the channel datastore, though the locks are not held at the same time. Be sure that you have no potential lock order issues here.
chan | The channel to check | |
[out] | core_id | If this is a valid CC recall, the core_id of the failed call will be placed in this output parameter |
monitor_type | Clarify which type of monitor type we are looking for if this is happening on a called channel. For incoming channels, this parameter is not used. |
0 | Either this is not a recall or it is but this channel is not part of the recall | |
non-zero | This is a recall and the channel in question is directly involved. |
Definition at line 3093 of file ccss.c.
References ast_assert, ast_channel_datastore_find(), ast_channel_get_device_name(), ast_channel_lock, AST_CHANNEL_NAME, ast_channel_unlock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), cc_recall_ds_data::core_id, ast_datastore::data, ast_cc_interface::device_name, cc_recall_ds_data::ignore, ast_cc_monitor::interface, cc_recall_ds_data::interface_tree, ast_cc_interface::monitor_type, cc_recall_ds_data::nested, cc_monitor_backend::next, and recall_ds_info.
Referenced by cc_core_init_instance(), sig_pri_call(), sip_call(), and wait_for_answer().
03094 { 03095 struct ast_datastore *recall_datastore; 03096 struct cc_recall_ds_data *recall_data; 03097 struct cc_monitor_tree *interface_tree; 03098 char device_name[AST_CHANNEL_NAME]; 03099 struct ast_cc_monitor *device_monitor; 03100 int core_id_candidate; 03101 03102 ast_assert(core_id != NULL); 03103 03104 *core_id = -1; 03105 03106 ast_channel_lock(chan); 03107 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03108 /* Obviously not a recall if the datastore isn't present */ 03109 ast_channel_unlock(chan); 03110 return 0; 03111 } 03112 03113 recall_data = recall_datastore->data; 03114 03115 if (recall_data->ignore) { 03116 /* Though this is a recall, the call to this particular interface is not part of the 03117 * recall either because this is a call forward or because this is not the first 03118 * invocation of Dial during this call 03119 */ 03120 ast_channel_unlock(chan); 03121 return 0; 03122 } 03123 03124 if (!recall_data->nested) { 03125 /* If the nested flag is not set, then this means that 03126 * the channel passed to this function is the caller making 03127 * the recall. This means that we shouldn't look through 03128 * the monitor tree for the channel because it shouldn't be 03129 * there. However, this is a recall though, so return true. 03130 */ 03131 *core_id = recall_data->core_id; 03132 ast_channel_unlock(chan); 03133 return 1; 03134 } 03135 03136 if (ast_strlen_zero(monitor_type)) { 03137 /* If someone passed a NULL or empty monitor type, then it is clear 03138 * the channel they passed in was an incoming channel, and so searching 03139 * the list of dialed interfaces is not going to be helpful. Just return 03140 * false immediately. 03141 */ 03142 ast_channel_unlock(chan); 03143 return 0; 03144 } 03145 03146 interface_tree = recall_data->interface_tree; 03147 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 03148 /* We grab the value of the recall_data->core_id so that we 03149 * can unlock the channel before we start looking through the 03150 * interface list. That way we don't have to worry about a possible 03151 * clash between the channel lock and the monitor tree lock. 03152 */ 03153 core_id_candidate = recall_data->core_id; 03154 ast_channel_unlock(chan); 03155 03156 /* 03157 * Now we need to find out if the channel device name 03158 * is in the list of interfaces in the called tree. 03159 */ 03160 AST_LIST_LOCK(interface_tree); 03161 AST_LIST_TRAVERSE(interface_tree, device_monitor, next) { 03162 if (!strcmp(device_monitor->interface->device_name, device_name) && 03163 !strcmp(device_monitor->interface->monitor_type, monitor_type)) { 03164 /* BOOM! Device is in the tree! We have a winner! */ 03165 *core_id = core_id_candidate; 03166 AST_LIST_UNLOCK(interface_tree); 03167 return 1; 03168 } 03169 } 03170 AST_LIST_UNLOCK(interface_tree); 03171 return 0; 03172 }
int ast_cc_monitor_callee_available | ( | const int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Alert the core that a device being monitored has become available.
core_id | The core ID of the corresponding CC transaction | |
debug |
0 | Request successfully queued | |
-1 | Request could not be queued |
Definition at line 3453 of file ccss.c.
References CC_CALLEE_READY, and cc_request_state_change().
Referenced by cc_generic_monitor_destructor(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), generic_monitor_devstate_tp_cb(), handle_cc_notify(), and sig_pri_handle_cis_subcmds().
03454 { 03455 va_list ap; 03456 int res; 03457 03458 va_start(ap, debug); 03459 res = cc_request_state_change(CC_CALLEE_READY, core_id, debug, ap); 03460 va_end(ap); 03461 return res; 03462 }
int ast_cc_monitor_count | ( | const char *const | name, | |
const char *const | type | |||
) |
Return the number of outstanding CC requests to a specific device.
name | The name of the monitored device | |
type | The type of the monitored device (e.g. "generic") |
Definition at line 4010 of file ccss.c.
References ao2_t_callback, ast_log_dynamic_level, cc_core_instances, count_monitors_cb_data::count, count_monitors_cb(), count_monitors_cb_data::device_name, and OBJ_NODATA.
Referenced by ast_queue_cc_frame().
04011 { 04012 struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,}; 04013 04014 ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents"); 04015 ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count); 04016 return data.count; 04017 }
int ast_cc_monitor_failed | ( | int | core_id, | |
const char *const | monitor_name, | |||
const char *const | debug, | |||
... | ||||
) |
Indicate that a failure has occurred on a specific monitor.
If there are no more devices left to monitor when this function is called, then the core will fail the CC transaction globally.
core_id | The core ID for the CC transaction | |
monitor_name | The name of the monitor on which the failure occurred | |
debug | A debug message to print to the CC log |
Definition at line 3599 of file ccss.c.
References ast_calloc, ast_free, ast_strdup, ast_taskprocessor_push(), ast_vasprintf, cc_core_taskprocessor, and cc_monitor_failed().
Referenced by ast_cc_available_timer_expire(), cc_handle_publish_error(), handle_response(), and sig_pri_handle_cis_subcmds().
03600 { 03601 struct ast_cc_monitor_failure_data *failure_data; 03602 int res; 03603 va_list ap; 03604 03605 if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) { 03606 return -1; 03607 } 03608 03609 if (!(failure_data->device_name = ast_strdup(monitor_name))) { 03610 ast_free(failure_data); 03611 return -1; 03612 } 03613 03614 va_start(ap, debug); 03615 if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) { 03616 va_end(ap); 03617 ast_free((char *)failure_data->device_name); 03618 ast_free(failure_data); 03619 return -1; 03620 } 03621 va_end(ap); 03622 03623 failure_data->core_id = core_id; 03624 03625 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_monitor_failed, failure_data); 03626 if (res) { 03627 ast_free((char *)failure_data->device_name); 03628 ast_free((char *)failure_data->debug); 03629 ast_free(failure_data); 03630 } 03631 return res; 03632 }
int ast_cc_monitor_party_b_free | ( | int | core_id | ) |
Alert a caller that though the callee has become free, the caller himself is not and may not call back.
When an ISDN PTMP monitor senses that his monitored party has become available, he will request the status of the called party. If he determines that the caller is currently not available, then he will call this function so that an appropriate message is sent to the caller.
Yes, you just read that correctly. The callee asks the caller what his current status is, and if the caller is currently unavailable, the monitor must send him a message anyway. WTF?
This function results in the agent's party_b_free callback being called. It is most likely that you will not need to actually implement the party_b_free callback in an agent because it is not likely that you will need to or even want to send a caller a message indicating the callee's status if the caller himself is not also free.
core_id | The core ID of the CC transaction |
0 | Successfully alerted the core that party B is free | |
-1 | Could not alert the core that party B is free |
Definition at line 3709 of file ccss.c.
References ast_taskprocessor_push(), cc_core_taskprocessor, cc_party_b_free(), cc_unref(), and find_cc_core_instance().
Referenced by sig_pri_handle_cis_subcmds().
03710 { 03711 int res; 03712 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03713 03714 if (!core_instance) { 03715 return -1; 03716 } 03717 03718 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_party_b_free, core_instance); 03719 if (res) { 03720 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03721 } 03722 return res; 03723 }
int ast_cc_monitor_register | ( | const struct ast_cc_monitor_callbacks * | callbacks | ) |
Register a set of monitor callbacks with the core.
callbacks | The callbacks used by the monitor implementation |
0 | Successfully registered | |
-1 | Failure to register |
Definition at line 862 of file ccss.c.
References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and cc_monitor_backend::next.
Referenced by ast_cc_init(), and load_module().
00863 { 00864 struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend)); 00865 00866 if (!backend) { 00867 return -1; 00868 } 00869 00870 backend->callbacks = callbacks; 00871 00872 AST_RWLIST_WRLOCK(&cc_monitor_backends); 00873 AST_RWLIST_INSERT_TAIL(&cc_monitor_backends, backend, next); 00874 AST_RWLIST_UNLOCK(&cc_monitor_backends); 00875 return 0; 00876 }
int ast_cc_monitor_request_acked | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate that an outbound entity has accepted our CC request.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3442 of file ccss.c.
References CC_ACTIVE, and cc_request_state_change().
Referenced by cc_generic_monitor_request_cc(), cc_stop_ringing(), handle_cc_notify(), and sig_pri_handle_cis_subcmds().
03443 { 03444 va_list ap; 03445 int res; 03446 03447 va_start(ap, debug); 03448 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap); 03449 va_end(ap); 03450 return res; 03451 }
int ast_cc_monitor_status_request | ( | int | core_id | ) |
Request the status of a caller or callers.
When an ISDN PTMP monitor senses that the callee has become available, it needs to know the current status of the caller in order to determine the appropriate response to send to the caller. In order to do this, the monitor calls this function. Responses will arrive asynchronously.
core_id | The core ID of the CC transaction |
0 | Successfully requested status | |
-1 | Failed to request status |
Definition at line 3644 of file ccss.c.
References ast_taskprocessor_push(), cc_core_taskprocessor, cc_status_request(), cc_unref(), and find_cc_core_instance().
Referenced by sig_pri_handle_cis_subcmds().
03645 { 03646 int res; 03647 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03648 03649 if (!core_instance) { 03650 return -1; 03651 } 03652 03653 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_request, core_instance); 03654 if (res) { 03655 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03656 } 03657 return res; 03658 }
int ast_cc_monitor_stop_ringing | ( | int | core_id | ) |
Alert a caller to stop ringing.
When an ISDN PTMP monitor becomes available, it is assumed that the agent will then cause the caller's phone to ring. In some cases, this is literally what happens. In other cases, it may be that the caller gets a visible indication on his phone that he may attempt to recall the callee. If multiple callers are recalled (since it may be possible to have a group of callers configured as a single party A), and one of those callers picks up his phone, then the ISDN PTMP monitor will alert the other callers to stop ringing. The agent's stop_ringing callback will be called, and it is up to the agent's driver to send an appropriate message to make his caller stop ringing.
core_id | The core ID of the CC transaction |
0 | Successfully requested for the phone to stop ringing | |
-1 | Could not request for the phone to stop ringing |
Definition at line 3681 of file ccss.c.
References ast_taskprocessor_push(), cc_core_taskprocessor, cc_stop_ringing(), cc_unref(), and find_cc_core_instance().
Referenced by sig_pri_handle_cis_subcmds().
03682 { 03683 int res; 03684 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03685 03686 if (!core_instance) { 03687 return -1; 03688 } 03689 03690 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_stop_ringing, core_instance); 03691 if (res) { 03692 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03693 } 03694 return res; 03695 }
void ast_cc_monitor_unregister | ( | const struct ast_cc_monitor_callbacks * | callbacks | ) |
Unregister a set of monitor callbacks with the core.
callbacks | The callbacks used by the monitor implementation |
0 | Successfully unregistered | |
-1 | Failure to unregister |
Definition at line 895 of file ccss.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cc_monitor_backend::callbacks, and cc_monitor_backend::next.
Referenced by __unload_module(), and unload_module().
00896 { 00897 struct cc_monitor_backend *backend; 00898 AST_RWLIST_WRLOCK(&cc_monitor_backends); 00899 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_monitor_backends, backend, next) { 00900 if (backend->callbacks == callbacks) { 00901 AST_RWLIST_REMOVE_CURRENT(next); 00902 ast_free(backend); 00903 break; 00904 } 00905 } 00906 AST_RWLIST_TRAVERSE_SAFE_END; 00907 AST_RWLIST_UNLOCK(&cc_monitor_backends); 00908 }
int ast_cc_offer | ( | struct ast_channel * | caller_chan | ) |
Offer CC to a caller.
caller_chan | The calling channel |
-1 | Error | |
0 | Success |
Definition at line 3406 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, cc_offer(), dialed_cc_interfaces::core_id, cc_recall_ds_data::core_id, ast_datastore::data, dialed_cc_interfaces_info, dialed_cc_interfaces::is_original_caller, and ast_channel::name.
Referenced by ast_hangup().
03407 { 03408 int core_id; 03409 int res = -1; 03410 struct ast_datastore *datastore; 03411 struct dialed_cc_interfaces *cc_interfaces; 03412 char cc_is_offerable; 03413 03414 ast_channel_lock(caller_chan); 03415 if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) { 03416 ast_channel_unlock(caller_chan); 03417 return res; 03418 } 03419 03420 cc_interfaces = datastore->data; 03421 cc_is_offerable = cc_interfaces->is_original_caller; 03422 core_id = cc_interfaces->core_id; 03423 ast_channel_unlock(caller_chan); 03424 03425 if (cc_is_offerable) { 03426 res = cc_offer(core_id, "CC offered to caller %s", caller_chan->name); 03427 } 03428 return res; 03429 }
int ast_cc_request_is_within_limits | ( | void | ) |
Check if the incoming CC request is within the bounds set by the cc_max_requests configuration option.
If this is not called and a state change to CC_CALLER_REQUESTED is made, then the core will still not allow for the request to succeed. However, if done this way, it may not be obvious to the requestor why the request failed.
0 | Not within the limits. Fail. | |
non-zero | Within the limits. Success. |
Definition at line 2164 of file ccss.c.
Referenced by cc_caller_requested(), cc_interfaces_datastore_init(), ccreq_exec(), and sig_pri_handle_cis_subcmds().
02165 { 02166 return cc_request_count < global_cc_max_requests; 02167 }
int ast_cc_set_param | ( | struct ast_cc_config_params * | params, | |
const char *const | name, | |||
const char * | value | |||
) |
set a CCSS configuration parameter, given its name
params | The parameter structure to set the value on | |
name | The name of the cc parameter | |
value | The value of the parameter |
0 | Success | |
-1 | Failure |
Definition at line 655 of file ccss.c.
References ast_log(), ast_set_cc_agent_dialstring(), ast_set_cc_agent_policy(), ast_set_cc_callback_macro(), ast_set_cc_max_agents(), ast_set_cc_max_monitors(), ast_set_cc_monitor_policy(), ast_set_cc_offer_timer(), ast_set_cc_recall_timer(), ast_set_ccbs_available_timer(), ast_set_ccnr_available_timer(), LOG_WARNING, str_to_agent_policy(), and str_to_monitor_policy().
Referenced by acf_cc_write(), and build_peer().
00657 { 00658 unsigned int value_as_uint; 00659 if (!strcasecmp(name, "cc_agent_policy")) { 00660 return ast_set_cc_agent_policy(params, str_to_agent_policy(value)); 00661 } else if (!strcasecmp(name, "cc_monitor_policy")) { 00662 return ast_set_cc_monitor_policy(params, str_to_monitor_policy(value)); 00663 } else if (!strcasecmp(name, "cc_agent_dialstring")) { 00664 ast_set_cc_agent_dialstring(params, value); 00665 } else if (!strcasecmp(name, "cc_callback_macro")) { 00666 ast_set_cc_callback_macro(params, value); 00667 return 0; 00668 } 00669 00670 if (!sscanf(value, "%30u", &value_as_uint) == 1) { 00671 return -1; 00672 } 00673 00674 if (!strcasecmp(name, "cc_offer_timer")) { 00675 ast_set_cc_offer_timer(params, value_as_uint); 00676 } else if (!strcasecmp(name, "ccnr_available_timer")) { 00677 ast_set_ccnr_available_timer(params, value_as_uint); 00678 } else if (!strcasecmp(name, "ccbs_available_timer")) { 00679 ast_set_ccbs_available_timer(params, value_as_uint); 00680 } else if (!strcasecmp(name, "cc_max_agents")) { 00681 ast_set_cc_max_agents(params, value_as_uint); 00682 } else if (!strcasecmp(name, "cc_max_monitors")) { 00683 ast_set_cc_max_monitors(params, value_as_uint); 00684 } else if (!strcasecmp(name, "cc_recall_timer")) { 00685 ast_set_cc_recall_timer(params, value_as_uint); 00686 } else { 00687 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name); 00688 return -1; 00689 } 00690 00691 return 0; 00692 }
const char* ast_get_cc_agent_dialstring | ( | struct ast_cc_config_params * | config | ) |
Get the cc_agent_dialstring.
config | The configuration to retrieve the cc_agent_dialstring from |
Definition at line 807 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and generic_recall().
00808 { 00809 return config->cc_agent_dialstring; 00810 }
enum ast_cc_agent_policies ast_get_cc_agent_policy | ( | struct ast_cc_config_params * | config | ) |
Get the cc_agent_policy.
config | The configuration to retrieve the policy from |
Definition at line 713 of file ccss.c.
References config.
Referenced by ast_cc_call_init(), ast_cc_get_param(), build_peer(), cc_core_init_instance(), and find_agent_callbacks().
00714 { 00715 return config->cc_agent_policy; 00716 }
const char* ast_get_cc_callback_macro | ( | struct ast_cc_config_params * | config | ) |
Get the name of the callback_macro.
config | The configuration to retrieve the callback_macro from |
Definition at line 841 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and generic_recall().
00842 { 00843 return config->cc_callback_macro; 00844 }
unsigned int ast_get_cc_max_agents | ( | struct ast_cc_config_params * | config | ) |
Get the cc_max_agents.
config | The configuration to retrieve the cc_max_agents from |
Definition at line 821 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and cc_core_init_instance().
00822 { 00823 return config->cc_max_agents; 00824 }
unsigned int ast_get_cc_max_monitors | ( | struct ast_cc_config_params * | config | ) |
Get the cc_max_monitors.
config | The configuration to retrieve the cc_max_monitors from |
Definition at line 831 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and ast_queue_cc_frame().
00832 { 00833 return config->cc_max_monitors; 00834 }
enum ast_cc_monitor_policies ast_get_cc_monitor_policy | ( | struct ast_cc_config_params * | config | ) |
Get the cc_monitor_policy.
config | The configuration to retrieve the cc_monitor_policy from |
Definition at line 730 of file ccss.c.
References config.
Referenced by analog_call(), ast_cc_call_failed(), ast_cc_get_param(), dahdi_cc_callback(), sig_pri_cc_generic_check(), and sip_handle_cc().
00731 { 00732 return config->cc_monitor_policy; 00733 }
unsigned int ast_get_cc_offer_timer | ( | struct ast_cc_config_params * | config | ) |
Get the cc_offer_timer.
config | The configuration to retrieve the cc_offer_timer from |
Definition at line 747 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), cc_generic_agent_start_offer_timer(), and sip_cc_agent_start_offer_timer().
00748 { 00749 return config->cc_offer_timer; 00750 }
unsigned int ast_get_cc_recall_timer | ( | struct ast_cc_config_params * | config | ) |
Get the cc_recall_timer.
config | The configuration to retrieve the cc_recall_timer from |
Definition at line 777 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and generic_recall().
00778 { 00779 return config->cc_recall_timer; 00780 }
unsigned int ast_get_ccbs_available_timer | ( | struct ast_cc_config_params * | config | ) |
Get the ccbs_available_timer.
config | The configuration to retrieve the ccbs_available_timer from |
Definition at line 792 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().
00793 { 00794 return config->ccbs_available_timer; 00795 }
unsigned int ast_get_ccnr_available_timer | ( | struct ast_cc_config_params * | config | ) |
Get the ccnr_available_timer.
config | The configuration to retrieve the ccnr_available_timer from |
Definition at line 762 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().
00763 { 00764 return config->ccnr_available_timer; 00765 }
void ast_handle_cc_control_frame | ( | struct ast_channel * | inbound, | |
struct ast_channel * | outbound, | |||
void * | frame_data | |||
) |
Properly react to a CC control frame.
Unless we are ignoring CC for some reason, we will always call this function when we read an AST_CONTROL_CC frame from an outbound channel.
This function will call cc_device_monitor_init to create the new cc_monitor for the device from which we read the frame. In addition, the new device will be added to the monitor tree on the dialed_cc_interfaces datastore on the inbound channel.
If this is the first AST_CONTROL_CC frame that we have handled for this call, then we will also initialize the CC core for this call.
Definition at line 1993 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_CC, ast_indicate_data(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_log_dynamic_level, call_destructor_with_no_monitor(), cc_core_init_instance(), cc_device_monitor_init(), cc_extension_monitor_change_is_valid(), cc_ref(), cc_service_to_string(), cc_unref(), cc_core_instance::core_id, dialed_cc_interfaces::core_id, ast_datastore::data, cc_control_payload::device_name, dialed_cc_interfaces_info, cc_control_payload::dialstring, ast_cc_monitor::dialstring, EVENT_FLAG_CC, find_cc_core_instance(), dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, dialed_cc_interfaces::is_original_caller, LOG_WARNING, manager_event, monitor, cc_control_payload::monitor_type, cc_monitor_backend::next, cc_control_payload::private_data, and cc_control_payload::service.
Referenced by ast_cc_busy_interface(), and ast_cc_call_failed().
01994 { 01995 char *device_name; 01996 char *dialstring; 01997 struct ast_cc_monitor *monitor; 01998 struct ast_datastore *cc_datastore; 01999 struct dialed_cc_interfaces *cc_interfaces; 02000 struct cc_control_payload *cc_data = frame_data; 02001 struct cc_core_instance *core_instance; 02002 02003 device_name = cc_data->device_name; 02004 dialstring = cc_data->dialstring; 02005 02006 ast_channel_lock(inbound); 02007 if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) { 02008 ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name); 02009 ast_channel_unlock(inbound); 02010 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02011 return; 02012 } 02013 02014 cc_interfaces = cc_datastore->data; 02015 02016 if (cc_interfaces->ignore) { 02017 ast_channel_unlock(inbound); 02018 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02019 return; 02020 } 02021 02022 if (!cc_interfaces->is_original_caller) { 02023 /* If the is_original_caller is not set on the *inbound* channel, then 02024 * it must be a local channel. As such, we do not want to create a core instance 02025 * or an agent for the local channel. Instead, we want to pass this along to the 02026 * other side of the local channel so that the original caller can benefit. 02027 */ 02028 ast_channel_unlock(inbound); 02029 ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data)); 02030 return; 02031 } 02032 02033 core_instance = find_cc_core_instance(cc_interfaces->core_id); 02034 if (!core_instance) { 02035 core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree, 02036 cc_interfaces->core_id, cc_data); 02037 if (!core_instance) { 02038 cc_interfaces->ignore = 1; 02039 ast_channel_unlock(inbound); 02040 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02041 return; 02042 } 02043 } 02044 02045 ast_channel_unlock(inbound); 02046 02047 /* Yeah this kind of sucks, but luckily most people 02048 * aren't dialing thousands of interfaces on every call 02049 * 02050 * This traversal helps us to not create duplicate monitors in 02051 * case a device queues multiple CC control frames. 02052 */ 02053 AST_LIST_LOCK(cc_interfaces->interface_tree); 02054 AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) { 02055 if (!strcmp(monitor->interface->device_name, device_name)) { 02056 ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n", 02057 core_instance->core_id, device_name); 02058 AST_LIST_UNLOCK(cc_interfaces->interface_tree); 02059 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance"); 02060 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02061 return; 02062 } 02063 } 02064 AST_LIST_UNLOCK(cc_interfaces->interface_tree); 02065 02066 if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) { 02067 ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name); 02068 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance"); 02069 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02070 return; 02071 } 02072 02073 AST_LIST_LOCK(cc_interfaces->interface_tree); 02074 cc_ref(monitor, "monitor tree's reference to the monitor"); 02075 AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next); 02076 AST_LIST_UNLOCK(cc_interfaces->interface_tree); 02077 02078 cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0); 02079 02080 manager_event(EVENT_FLAG_CC, "CCAvailable", 02081 "CoreID: %d\r\n" 02082 "Callee: %s\r\n" 02083 "Service: %s\r\n", 02084 cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service) 02085 ); 02086 02087 cc_unref(core_instance, "Done with core_instance after handling CC control frame"); 02088 cc_unref(monitor, "Unref reference from allocating monitor"); 02089 }
void ast_ignore_cc | ( | struct ast_channel * | chan | ) |
Mark the channel to ignore further CC activity.
chan | The channel for which further CC processing should be ignored. |
void |
Definition at line 3375 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore::data, dialed_cc_interfaces_info, cc_recall_ds_data::ignore, dialed_cc_interfaces::ignore, and recall_ds_info.
Referenced by dial_exec_full(), and do_forward().
03376 { 03377 struct ast_datastore *cc_datastore; 03378 struct ast_datastore *cc_recall_datastore; 03379 struct dialed_cc_interfaces *cc_interfaces; 03380 struct cc_recall_ds_data *recall_cc_data; 03381 03382 ast_channel_lock(chan); 03383 if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) { 03384 cc_interfaces = cc_datastore->data; 03385 cc_interfaces->ignore = 1; 03386 } 03387 03388 if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03389 recall_cc_data = cc_recall_datastore->data; 03390 recall_cc_data->ignore = 1; 03391 } 03392 ast_channel_unlock(chan); 03393 }
int ast_queue_cc_frame | ( | struct ast_channel * | chan, | |
const char *const | monitor_type, | |||
const char *const | dialstring, | |||
enum ast_cc_service_type | service, | |||
void * | private_data | |||
) |
Queue an AST_CONTROL_CC frame.
chan | The channel onto which to queue the frame | |
monitor_type | The type of monitor to use when CC is requested | |
dialstring | The dial string used to call the device | |
service | The type of CC service the device is willing to offer | |
private_data | If a native monitor is being used, and some channel-driver-specific private data has been allocated, then this parameter should contain a pointer to that data. If using a generic monitor, this parameter should remain NULL. Note that if this function should fail at some point, it is the responsibility of the caller to free the private data upon return. |
0 | Success | |
-1 | Error |
Definition at line 3807 of file ccss.c.
References ast_cc_build_frame(), ast_cc_monitor_count(), ast_channel_get_cc_config_params(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_frfree, ast_get_cc_max_monitors(), ast_log(), ast_queue_frame(), and LOG_NOTICE.
Referenced by analog_call(), sig_pri_cc_generic_check(), and sip_handle_cc().
03809 { 03810 struct ast_frame frame = {0,}; 03811 char device_name[AST_CHANNEL_NAME]; 03812 int retval; 03813 struct ast_cc_config_params *cc_params; 03814 03815 cc_params = ast_channel_get_cc_config_params(chan); 03816 if (!cc_params) { 03817 return -1; 03818 } 03819 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 03820 if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) { 03821 ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name); 03822 return -1; 03823 } 03824 03825 if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) { 03826 /* Frame building failed. We can't use this. */ 03827 return -1; 03828 } 03829 retval = ast_queue_frame(chan, &frame); 03830 ast_frfree(&frame); 03831 return retval; 03832 }
void ast_set_cc_agent_dialstring | ( | struct ast_cc_config_params * | config, | |
const char *const | value | |||
) |
Set the cc_agent_dialstring.
config | The configuration to set the cc_agent_dialstring on | |
value | The new cc_agent_dialstring we want to change to |
void |
Definition at line 812 of file ccss.c.
References ast_copy_string(), ast_strlen_zero(), and config.
Referenced by ast_cc_set_param().
00813 { 00814 if (ast_strlen_zero(value)) { 00815 config->cc_agent_dialstring[0] = '\0'; 00816 } else { 00817 ast_copy_string(config->cc_agent_dialstring, value, sizeof(config->cc_agent_dialstring)); 00818 } 00819 }
int ast_set_cc_agent_policy | ( | struct ast_cc_config_params * | config, | |
enum ast_cc_agent_policies | value | |||
) |
Set the cc_agent_policy.
config | The configuration to set the cc_agent_policy on | |
value | The new cc_agent_policy we want to change to |
0 | Success | |
-1 | Failure (likely due to bad input) |
Definition at line 718 of file ccss.c.
References AST_CC_AGENT_GENERIC, and config.
Referenced by ast_cc_set_param(), and build_peer().
00719 { 00720 /* Screw C and its weak type checking for making me have to do this 00721 * validation at runtime. 00722 */ 00723 if (value < AST_CC_AGENT_NEVER || value > AST_CC_AGENT_GENERIC) { 00724 return -1; 00725 } 00726 config->cc_agent_policy = value; 00727 return 0; 00728 }
void ast_set_cc_callback_macro | ( | struct ast_cc_config_params * | config, | |
const char *const | value | |||
) |
Set the callback_macro name.
config | The configuration to set the callback_macro on | |
value | The new callback macro we want to change to |
void |
Definition at line 846 of file ccss.c.
References ast_copy_string(), ast_strlen_zero(), and config.
Referenced by ast_cc_set_param().
00847 { 00848 if (ast_strlen_zero(value)) { 00849 config->cc_callback_macro[0] = '\0'; 00850 } else { 00851 ast_copy_string(config->cc_callback_macro, value, sizeof(config->cc_callback_macro)); 00852 } 00853 }
int ast_set_cc_interfaces_chanvar | ( | struct ast_channel * | chan, | |
const char *const | extension | |||
) |
Set the CC_INTERFACES channel variable for a channel using an extension as a starting point.
chan | The channel to set the CC_INTERFACES variable on | |
extension | The name of the extension for which we're setting the variable. This should be in the form of "exten@context" |
Definition at line 3323 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_str_buffer(), ast_str_create(), build_cc_interfaces_chanvar(), cc_recall_ds_data::core_id, ast_datastore::data, ast_cc_interface::device_name, ast_cc_monitor::interface, cc_recall_ds_data::interface_tree, cc_monitor_backend::next, pbx_builtin_setvar_helper(), recall_ds_info, and str.
Referenced by local_call().
03324 { 03325 struct ast_datastore *recall_datastore; 03326 struct cc_monitor_tree *interface_tree; 03327 struct ast_cc_monitor *monitor_iter; 03328 struct cc_recall_ds_data *recall_data; 03329 struct ast_str *str = ast_str_create(64); 03330 int core_id; 03331 03332 if (!str) { 03333 return -1; 03334 } 03335 03336 ast_channel_lock(chan); 03337 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03338 ast_channel_unlock(chan); 03339 ast_free(str); 03340 return -1; 03341 } 03342 recall_data = recall_datastore->data; 03343 interface_tree = recall_data->interface_tree; 03344 core_id = recall_data->core_id; 03345 ast_channel_unlock(chan); 03346 03347 AST_LIST_LOCK(interface_tree); 03348 AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) { 03349 if (!strcmp(monitor_iter->interface->device_name, extension)) { 03350 break; 03351 } 03352 } 03353 03354 if (!monitor_iter) { 03355 /* We couldn't find this extension. This may be because 03356 * we have been directed into an unexpected extension because 03357 * the admin has changed a CC_INTERFACES variable at some point. 03358 */ 03359 AST_LIST_UNLOCK(interface_tree); 03360 ast_free(str); 03361 return -1; 03362 } 03363 03364 build_cc_interfaces_chanvar(monitor_iter, str); 03365 AST_LIST_UNLOCK(interface_tree); 03366 03367 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str)); 03368 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n", 03369 core_id, ast_str_buffer(str)); 03370 03371 ast_free(str); 03372 return 0; 03373 }
void ast_set_cc_max_agents | ( | struct ast_cc_config_params * | config, | |
unsigned int | value | |||
) |
Set the cc_max_agents.
config | The configuration to set the cc_max_agents on | |
value | The new cc_max_agents we want to change to |
void |
Definition at line 826 of file ccss.c.
References config.
Referenced by ast_cc_set_param().
void ast_set_cc_max_monitors | ( | struct ast_cc_config_params * | config, | |
unsigned int | value | |||
) |
Set the cc_max_monitors.
config | The configuration to set the cc_max_monitors on | |
value | The new cc_max_monitors we want to change to |
void |
Definition at line 836 of file ccss.c.
References config.
Referenced by ast_cc_set_param().
int ast_set_cc_monitor_policy | ( | struct ast_cc_config_params * | config, | |
enum ast_cc_monitor_policies | value | |||
) |
Set the cc_monitor_policy.
config | The configuration to set the cc_monitor_policy on | |
value | The new cc_monitor_policy we want to change to |
0 | Success | |
-1 | Failure (likely due to bad input) |
Definition at line 735 of file ccss.c.
References AST_CC_MONITOR_ALWAYS, and config.
Referenced by ast_cc_set_param().
00736 { 00737 /* Screw C and its weak type checking for making me have to do this 00738 * validation at runtime. 00739 */ 00740 if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) { 00741 return -1; 00742 } 00743 config->cc_monitor_policy = value; 00744 return 0; 00745 }
void ast_set_cc_offer_timer | ( | struct ast_cc_config_params * | config, | |
unsigned int | value | |||
) |
Set the cc_offer_timer.
config | The configuration to set the cc_offer_timer on | |
value | The new cc_offer_timer we want to change to |
void |
Definition at line 752 of file ccss.c.
References ast_log(), config, and LOG_WARNING.
Referenced by ast_cc_set_param().
00753 { 00754 /* 0 is an unreasonable value for any timer. Stick with the default */ 00755 if (value == 0) { 00756 ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer); 00757 return; 00758 } 00759 config->cc_offer_timer = value; 00760 }
void ast_set_cc_recall_timer | ( | struct ast_cc_config_params * | config, | |
unsigned int | value | |||
) |
Set the cc_recall_timer.
config | The configuration to set the cc_recall_timer on | |
value | The new cc_recall_timer we want to change to |
void |
Definition at line 782 of file ccss.c.
References ast_log(), config, and LOG_WARNING.
Referenced by ast_cc_set_param().
00783 { 00784 /* 0 is an unreasonable value for any timer. Stick with the default */ 00785 if (value == 0) { 00786 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->cc_recall_timer); 00787 return; 00788 } 00789 config->cc_recall_timer = value; 00790 }
void ast_set_ccbs_available_timer | ( | struct ast_cc_config_params * | config, | |
unsigned int | value | |||
) |
Set the ccbs_available_timer.
config | The configuration to set the ccbs_available_timer on | |
value | The new ccbs_available_timer we want to change to |
void |
Definition at line 797 of file ccss.c.
References ast_log(), config, and LOG_WARNING.
Referenced by ast_cc_set_param().
00798 { 00799 /* 0 is an unreasonable value for any timer. Stick with the default */ 00800 if (value == 0) { 00801 ast_log(LOG_WARNING, "0 is an invalid value for ccbs_available_timer. Retaining value as %u\n", config->ccbs_available_timer); 00802 return; 00803 } 00804 config->ccbs_available_timer = value; 00805 }
void ast_set_ccnr_available_timer | ( | struct ast_cc_config_params * | config, | |
unsigned int | value | |||
) |
Set the ccnr_available_timer.
config | The configuration to set the ccnr_available_timer on | |
value | The new ccnr_available_timer we want to change to |
void |
Definition at line 767 of file ccss.c.
References ast_log(), config, and LOG_WARNING.
Referenced by ast_cc_set_param().
00768 { 00769 /* 0 is an unreasonable value for any timer. Stick with the default */ 00770 if (value == 0) { 00771 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->ccnr_available_timer); 00772 return; 00773 } 00774 config->ccnr_available_timer = value; 00775 }
int ast_setup_cc_recall_datastore | ( | struct ast_channel * | chan, | |
const int | core_id | |||
) |
Set up a CC recall datastore on a channel.
This function must be called by the implementer once it has been detected that an inbound call is a cc_recall. After allocating the channel, call this function, followed by ast_cc_set_cc_interfaces_chanvar. While it would be nice to be able to have the core do this automatically, it just cannot be done given the current architecture.
Definition at line 3060 of file ccss.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_free, cc_ref(), cc_unref(), ast_datastore::data, DATASTORE_INHERIT_FOREVER, find_cc_core_instance(), ast_datastore::inheritance, cc_core_instance::monitors, and recall_ds_info.
Referenced by generic_recall(), handle_request_invite(), and sig_pri_handle_subcmds().
03061 { 03062 struct ast_datastore *recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL); 03063 struct cc_recall_ds_data *recall_data; 03064 struct cc_core_instance *core_instance; 03065 03066 if (!recall_datastore) { 03067 return -1; 03068 } 03069 03070 if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) { 03071 ast_datastore_free(recall_datastore); 03072 return -1; 03073 } 03074 03075 if (!(core_instance = find_cc_core_instance(core_id))) { 03076 ast_free(recall_data); 03077 ast_datastore_free(recall_datastore); 03078 return -1; 03079 } 03080 03081 recall_data->interface_tree = cc_ref(core_instance->monitors, 03082 "Bump refcount for monitor tree for recall datastore"); 03083 recall_data->core_id = core_id; 03084 recall_datastore->data = recall_data; 03085 recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER; 03086 ast_channel_lock(chan); 03087 ast_channel_datastore_add(chan, recall_datastore); 03088 ast_channel_unlock(chan); 03089 cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref"); 03090 return 0; 03091 }
static void build_cc_interfaces_chanvar | ( | struct ast_cc_monitor * | starting_point, | |
struct ast_str * | str | |||
) | [static] |
Definition at line 3243 of file ccss.c.
References AST_LIST_NEXT, AST_LIST_TRAVERSE, ast_log(), ast_str_strlen(), ast_str_truncate(), cc_unique_append(), extension_monitor_pvt::child_dialstrings, ast_cc_interface::device_name, ast_cc_monitor::dialstring, ast_cc_monitor::id, ast_cc_monitor::interface, extension_child_dialstring::is_valid, LOG_ERROR, cc_monitor_backend::next, extension_child_dialstring::original_dialstring, ast_cc_monitor::parent_id, ast_cc_monitor::private_data, and str.
Referenced by ast_cc_agent_set_interfaces_chanvar(), and ast_set_cc_interfaces_chanvar().
03244 { 03245 struct extension_monitor_pvt *extension_pvt; 03246 struct extension_child_dialstring *child_dialstring; 03247 struct ast_cc_monitor *monitor_iter = starting_point; 03248 int top_level_id = starting_point->id; 03249 size_t length; 03250 03251 /* Init to an empty string. */ 03252 ast_str_truncate(str, 0); 03253 03254 /* First we need to take all of the is_valid child_dialstrings from 03255 * the extension monitor we found and add them to the CC_INTERFACES 03256 * chanvar 03257 */ 03258 extension_pvt = starting_point->private_data; 03259 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) { 03260 if (child_dialstring->is_valid) { 03261 cc_unique_append(str, child_dialstring->original_dialstring); 03262 } 03263 } 03264 03265 /* And now we get the dialstrings from each of the device monitors */ 03266 while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) { 03267 if (monitor_iter->parent_id == top_level_id) { 03268 cc_unique_append(str, monitor_iter->dialstring); 03269 } 03270 } 03271 03272 /* str will have an extra '&' tacked onto the end of it, so we need 03273 * to get rid of that. 03274 */ 03275 length = ast_str_strlen(str); 03276 if (length) { 03277 ast_str_truncate(str, length - 1); 03278 } 03279 if (length <= 1) { 03280 /* Nothing to recall? This should not happen. */ 03281 ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n", 03282 starting_point->interface->device_name); 03283 } 03284 }
static void call_destructor_with_no_monitor | ( | const char *const | monitor_type, | |
void * | private_data | |||
) | [static] |
Definition at line 1891 of file ccss.c.
References ast_cc_monitor_callbacks::destructor, and find_monitor_callbacks().
Referenced by ast_cc_busy_interface(), and ast_handle_cc_control_frame().
01892 { 01893 const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type); 01894 01895 if (!monitor_callbacks) { 01896 return; 01897 } 01898 01899 monitor_callbacks->destructor(private_data); 01900 }
static void cancel_available_timer | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2876 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, and cc_monitor_backend::next.
Referenced by cc_recalling().
02877 { 02878 struct ast_cc_monitor *monitor_iter; 02879 AST_LIST_LOCK(core_instance->monitors); 02880 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02881 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02882 if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) { 02883 AST_LIST_REMOVE_CURRENT(next); 02884 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02885 monitor_iter->interface->device_name, 1); 02886 cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor"); 02887 } 02888 } 02889 } 02890 AST_LIST_TRAVERSE_SAFE_END; 02891 02892 if (!has_device_monitors(core_instance)) { 02893 ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers"); 02894 } 02895 AST_LIST_UNLOCK(core_instance->monitors); 02896 }
static int cc_active | ( | struct cc_core_instance * | core_instance, | |
struct cc_state_change_args * | args, | |||
enum cc_state | previous_state | |||
) | [static] |
Definition at line 2809 of file ccss.c.
References cc_core_instance::agent, AST_CC_AGENT_RESPONSE_SUCCESS, ast_cc_agent::callbacks, CC_CALLER_BUSY, CC_CALLER_REQUESTED, cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, manager_event, ast_cc_agent_callbacks::respond, and unsuspend().
02810 { 02811 /* Either 02812 * 1. Callee accepted CC request, call agent's ack callback. 02813 * 2. Caller became available, call agent's stop_monitoring callback and 02814 * call monitor's unsuspend callback. 02815 */ 02816 if (previous_state == CC_CALLER_REQUESTED) { 02817 core_instance->agent->callbacks->respond(core_instance->agent, 02818 AST_CC_AGENT_RESPONSE_SUCCESS); 02819 manager_event(EVENT_FLAG_CC, "CCRequestAcknowledged", 02820 "CoreID: %d\r\n" 02821 "Caller: %s\r\n", 02822 core_instance->core_id, core_instance->agent->device_name); 02823 } else if (previous_state == CC_CALLER_BUSY) { 02824 manager_event(EVENT_FLAG_CC, "CCCallerStopMonitoring", 02825 "CoreID: %d\r\n" 02826 "Caller: %s\r\n", 02827 core_instance->core_id, core_instance->agent->device_name); 02828 unsuspend(core_instance); 02829 } 02830 /* Not possible for previous_state to be anything else due to the is_state_change_valid check at the beginning */ 02831 return 0; 02832 }
static int cc_agent_callback_helper | ( | void * | obj, | |
void * | args, | |||
int | flags | |||
) | [static] |
Definition at line 401 of file ccss.c.
References cc_core_instance::agent, cc_callback_helper::args, ast_cc_agent::callbacks, cc_callback_helper::function, cc_callback_helper::type, and ast_cc_agent_callbacks::type.
Referenced by ast_cc_agent_callback().
00402 { 00403 struct cc_core_instance *core_instance = obj; 00404 struct cc_callback_helper *helper = args; 00405 00406 if (strcmp(core_instance->agent->callbacks->type, helper->type)) { 00407 return 0; 00408 } 00409 00410 return helper->function(core_instance->agent, helper->args, flags); 00411 }
static struct ast_cc_agent* cc_agent_init | ( | struct ast_channel * | caller_chan, | |
const char *const | caller_name, | |||
const int | core_id, | |||
struct cc_monitor_tree * | interface_tree | |||
) | [static] |
Definition at line 2225 of file ccss.c.
References agent_destroy(), ao2_t_alloc, ast_cc_config_params_init, ast_cc_copy_config_params(), ast_channel_get_cc_config_params(), ast_log_dynamic_level, cc_unref(), check_callback_sanity(), ast_cc_agent::core_id, and find_agent_callbacks().
Referenced by cc_core_init_instance().
02228 { 02229 struct ast_cc_agent *agent; 02230 struct ast_cc_config_params *cc_params; 02231 02232 if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy, 02233 "Allocating new ast_cc_agent"))) { 02234 return NULL; 02235 } 02236 02237 agent->core_id = core_id; 02238 strcpy(agent->device_name, caller_name); 02239 02240 cc_params = ast_channel_get_cc_config_params(caller_chan); 02241 if (!cc_params) { 02242 cc_unref(agent, "Could not get channel config params."); 02243 return NULL; 02244 } 02245 if (!(agent->cc_params = ast_cc_config_params_init())) { 02246 cc_unref(agent, "Could not init agent config params."); 02247 return NULL; 02248 } 02249 ast_cc_copy_config_params(agent->cc_params, cc_params); 02250 02251 if (!(agent->callbacks = find_agent_callbacks(caller_chan))) { 02252 cc_unref(agent, "Could not find agent callbacks."); 02253 return NULL; 02254 } 02255 check_callback_sanity(agent->callbacks); 02256 02257 if (agent->callbacks->init(agent, caller_chan)) { 02258 cc_unref(agent, "Agent init callback failed."); 02259 return NULL; 02260 } 02261 ast_log_dynamic_level(cc_logger_level, "Core %d: Created an agent for caller %s\n", 02262 agent->core_id, agent->device_name); 02263 return agent; 02264 }
static int cc_available | ( | struct cc_core_instance * | core_instance, | |
struct cc_state_change_args * | args, | |||
enum cc_state | previous_state | |||
) | [static] |
Definition at line 2690 of file ccss.c.
References ast_log(), and LOG_WARNING.
02691 { 02692 /* This should never happen... */ 02693 ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n"); 02694 return -1; 02695 }
static int cc_build_payload | ( | struct ast_channel * | chan, | |
struct ast_cc_config_params * | cc_params, | |||
const char * | monitor_type, | |||
const char *const | device_name, | |||
const char * | dialstring, | |||
enum ast_cc_service_type | service, | |||
void * | private_data, | |||
struct cc_control_payload * | payload | |||
) | [static] |
Definition at line 3779 of file ccss.c.
References ast_cc_copy_config_params(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), cc_control_payload::config_params, ast_datastore::data, cc_control_payload::device_name, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces_info, cc_control_payload::dialstring, cc_control_payload::monitor_type, cc_control_payload::parent_interface_id, cc_control_payload::private_data, and cc_control_payload::service.
Referenced by ast_cc_build_frame(), ast_cc_busy_interface(), and ast_cc_call_failed().
03782 { 03783 struct ast_datastore *datastore; 03784 struct dialed_cc_interfaces *cc_interfaces; 03785 int dial_parent_id; 03786 03787 ast_channel_lock(chan); 03788 datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL); 03789 if (!datastore) { 03790 ast_channel_unlock(chan); 03791 return -1; 03792 } 03793 cc_interfaces = datastore->data; 03794 dial_parent_id = cc_interfaces->dial_parent_id; 03795 ast_channel_unlock(chan); 03796 03797 payload->monitor_type = monitor_type; 03798 payload->private_data = private_data; 03799 payload->service = service; 03800 ast_cc_copy_config_params(&payload->config_params, cc_params); 03801 payload->parent_interface_id = dial_parent_id; 03802 ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name)); 03803 ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring)); 03804 return 0; 03805 }
static int cc_callee_ready | ( | struct cc_core_instance * | core_instance, | |
struct cc_state_change_args * | args, | |||
enum cc_state | previous_state | |||
) | [static] |
Definition at line 2834 of file ccss.c.
References cc_core_instance::agent, ast_cc_agent::callbacks, and ast_cc_agent_callbacks::callee_available.
02835 { 02836 core_instance->agent->callbacks->callee_available(core_instance->agent); 02837 return 0; 02838 }
static int cc_caller_busy | ( | struct cc_core_instance * | core_instance, | |
struct cc_state_change_args * | args, | |||
enum cc_state | previous_state | |||
) | [static] |
Definition at line 2862 of file ccss.c.
References cc_core_instance::agent, ast_cc_agent::callbacks, cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, manager_event, ast_cc_agent_callbacks::start_monitoring, and suspend().
02863 { 02864 /* Callee was available, but caller was busy, call agent's begin_monitoring callback 02865 * and call monitor's suspend callback. 02866 */ 02867 suspend(core_instance); 02868 core_instance->agent->callbacks->start_monitoring(core_instance->agent); 02869 manager_event(EVENT_FLAG_CC, "CCCallerStartMonitoring", 02870 "CoreID: %d\r\n" 02871 "Caller: %s\r\n", 02872 core_instance->core_id, core_instance->agent->device_name); 02873 return 0; 02874 }
static int cc_caller_offered | ( | struct cc_core_instance * | core_instance, | |
struct cc_state_change_args * | args, | |||
enum cc_state | previous_state | |||
) | [static] |
Definition at line 2697 of file ccss.c.
References cc_core_instance::agent, ast_cc_failed(), ast_log_dynamic_level, ast_cc_agent::callbacks, ast_cc_config_params::cc_offer_timer, ast_cc_agent::cc_params, cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, manager_event, and ast_cc_agent_callbacks::start_offer_timer.
02698 { 02699 if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) { 02700 ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n", 02701 core_instance->agent->device_name); 02702 return -1; 02703 } 02704 manager_event(EVENT_FLAG_CC, "CCOfferTimerStart", 02705 "CoreID: %d\r\n" 02706 "Caller: %s\r\n" 02707 "Expires: %u\r\n", 02708 core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer); 02709 ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n", 02710 core_instance->core_id, core_instance->agent->device_name); 02711 return 0; 02712 }
static int cc_caller_requested | ( | struct cc_core_instance * | core_instance, | |
struct cc_state_change_args * | args, | |||
enum cc_state | previous_state | |||
) | [static] |
Definition at line 2773 of file ccss.c.
References cc_core_instance::agent, AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY, ast_cc_failed(), ast_cc_request_is_within_limits(), ast_log(), ast_cc_agent::callbacks, cc_core_instance::core_id, LOG_WARNING, request_cc(), ast_cc_agent_callbacks::respond, and ast_cc_agent_callbacks::stop_offer_timer.
02774 { 02775 if (!ast_cc_request_is_within_limits()) { 02776 ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n"); 02777 core_instance->agent->callbacks->respond(core_instance->agent, 02778 AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY); 02779 ast_cc_failed(core_instance->core_id, "Too many requests in the system"); 02780 return -1; 02781 } 02782 core_instance->agent->callbacks->stop_offer_timer(core_instance->agent); 02783 request_cc(core_instance); 02784 return 0; 02785 }
static int cc_cli_output_status | ( | void * | data | ) | [static] |
Definition at line 4083 of file ccss.c.
References ao2_container_count(), ao2_t_callback, ast_cli(), ast_free, cc_core_instances, OBJ_NODATA, and print_stats_cb().
Referenced by handle_cc_status().
04084 { 04085 int *cli_fd = data; 04086 int count = ao2_container_count(cc_core_instances); 04087 04088 if (!count) { 04089 ast_cli(*cli_fd, "There are currently no active call completion transactions\n"); 04090 } else { 04091 ast_cli(*cli_fd, "%d Call completion transactions\n", count); 04092 ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n"); 04093 ast_cli(*cli_fd, "----------------------------------------------------------------------------\n"); 04094 ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI"); 04095 } 04096 ast_free(cli_fd); 04097 return 0; 04098 }
static void cc_cli_print_monitor_stats | ( | struct ast_cc_monitor * | monitor, | |
int | fd, | |||
int | parent_id | |||
) | [static] |
Definition at line 4050 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cli(), AST_LIST_NEXT, cc_service_to_string(), ast_cc_monitor::id, monitor, cc_monitor_backend::next, and ast_cc_monitor::parent_id.
Referenced by print_stats_cb().
04051 { 04052 struct ast_cc_monitor *child_monitor_iter = monitor; 04053 if (!monitor) { 04054 return; 04055 } 04056 04057 ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name); 04058 if (monitor->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 04059 ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered)); 04060 } 04061 ast_cli(fd, "\n"); 04062 04063 while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) { 04064 if (child_monitor_iter->parent_id == monitor->id) { 04065 cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id); 04066 } 04067 } 04068 }
static int cc_complete | ( | struct cc_core_instance * | core_instance, | |
struct cc_state_change_args * | args, | |||
enum cc_state | previous_state | |||
) | [static] |
Definition at line 2910 of file ccss.c.
References cc_core_instance::agent, ao2_t_unlink, cc_core_instances, cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, and manager_event.
02911 { 02912 /* Recall has made progress, call agent and monitor destructor functions 02913 */ 02914 manager_event(EVENT_FLAG_CC, "CCRecallComplete", 02915 "CoreID: %d\r\n" 02916 "Caller: %s\r\n", 02917 core_instance->core_id, core_instance->agent->device_name); 02918 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed"); 02919 return 0; 02920 }
static struct cc_core_instance * cc_core_init_instance | ( | struct ast_channel * | caller_chan, | |
struct cc_monitor_tree * | called_tree, | |||
const int | core_id, | |||
struct cc_control_payload * | cc_data | |||
) | [static] |
Definition at line 2573 of file ccss.c.
References ao2_t_alloc, ao2_t_link, AST_CC_AGENT_GENERIC, ast_cc_is_recall(), ast_channel_get_cc_config_params(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_get_cc_agent_policy(), ast_get_cc_max_agents(), ast_log_dynamic_level, cc_agent_init(), cc_core_instance_destructor(), cc_core_instances, cc_ref(), cc_unref(), count_agents(), and kill_duplicate_offers().
Referenced by ast_handle_cc_control_frame().
02575 { 02576 char caller[AST_CHANNEL_NAME]; 02577 struct cc_core_instance *core_instance; 02578 struct ast_cc_config_params *cc_params; 02579 long agent_count; 02580 int recall_core_id; 02581 02582 ast_channel_get_device_name(caller_chan, caller, sizeof(caller)); 02583 cc_params = ast_channel_get_cc_config_params(caller_chan); 02584 if (!cc_params) { 02585 ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n", 02586 caller); 02587 return NULL; 02588 } 02589 /* First, we need to kill off other pending CC offers from caller. If the caller is going 02590 * to request a CC service, it may only be for the latest call he made. 02591 */ 02592 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) { 02593 kill_duplicate_offers(caller); 02594 } 02595 02596 ast_cc_is_recall(caller_chan, &recall_core_id, NULL); 02597 agent_count = count_agents(caller, recall_core_id); 02598 if (agent_count >= ast_get_cc_max_agents(cc_params)) { 02599 ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller); 02600 return NULL; 02601 } 02602 02603 /* Generic agents can only have a single outstanding CC request per caller. */ 02604 if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) { 02605 ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n"); 02606 return NULL; 02607 } 02608 02609 /* Next, we need to create the core instance for this call */ 02610 if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) { 02611 return NULL; 02612 } 02613 02614 core_instance->core_id = core_id; 02615 if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) { 02616 cc_unref(core_instance, "Couldn't allocate agent, unref core_instance"); 02617 return NULL; 02618 } 02619 02620 core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree"); 02621 02622 ao2_t_link(cc_core_instances, core_instance, "Link core instance into container"); 02623 02624 return core_instance; 02625 }
static int cc_core_instance_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 380 of file ccss.c.
References CMP_MATCH, CMP_STOP, and cc_core_instance::core_id.
Referenced by ast_cc_init().
00381 { 00382 struct cc_core_instance *core_instance1 = obj; 00383 struct cc_core_instance *core_instance2 = arg; 00384 00385 return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0; 00386 }
static void cc_core_instance_destructor | ( | void * | data | ) | [static] |
Definition at line 2561 of file ccss.c.
References cc_core_instance::agent, ast_log_dynamic_level, cc_unref(), cc_core_instance::core_id, and cc_core_instance::monitors.
Referenced by cc_core_init_instance().
02562 { 02563 struct cc_core_instance *core_instance = data; 02564 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id); 02565 if (core_instance->agent) { 02566 cc_unref(core_instance->agent, "Core instance is done with the agent now"); 02567 } 02568 if (core_instance->monitors) { 02569 core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list"); 02570 } 02571 }
static int cc_core_instance_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 374 of file ccss.c.
References cc_core_instance::core_id.
Referenced by ast_cc_init().
00375 { 00376 const struct cc_core_instance *core_instance = obj; 00377 return core_instance->core_id; 00378 }
static struct ast_cc_monitor* cc_device_monitor_init | ( | const char *const | device_name, | |
const char *const | dialstring, | |||
const struct cc_control_payload * | cc_data, | |||
int | core_id | |||
) | [static] |
Definition at line 1927 of file ccss.c.
References ao2_t_alloc, ast_atomic_fetchadd_int(), ast_cc_config_params_init, ast_cc_copy_config_params(), AST_CC_DEVICE_MONITOR, ast_log_dynamic_level, ast_strdup, cc_interface_destroy(), cc_monitor_destroy(), cc_unref(), cc_control_payload::config_params, find_monitor_callbacks(), monitor, cc_control_payload::monitor_type, ast_cc_monitor::parent_id, cc_control_payload::parent_interface_id, cc_control_payload::private_data, and cc_control_payload::service.
Referenced by ast_handle_cc_control_frame().
01928 { 01929 struct ast_cc_interface *cc_interface; 01930 struct ast_cc_monitor *monitor; 01931 size_t device_name_len = strlen(device_name); 01932 int parent_id = cc_data->parent_interface_id; 01933 01934 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy, 01935 "Allocating new ast_cc_interface"))) { 01936 return NULL; 01937 } 01938 01939 if (!(cc_interface->config_params = ast_cc_config_params_init())) { 01940 cc_unref(cc_interface, "Failed to allocate config params, unref interface"); 01941 return NULL; 01942 } 01943 01944 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) { 01945 cc_unref(cc_interface, "Failed to allocate monitor, unref interface"); 01946 return NULL; 01947 } 01948 01949 if (!(monitor->dialstring = ast_strdup(dialstring))) { 01950 cc_unref(monitor, "Failed to copy dialable name. Unref monitor"); 01951 cc_unref(cc_interface, "Failed to copy dialable name"); 01952 return NULL; 01953 } 01954 01955 if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) { 01956 cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor"); 01957 cc_unref(cc_interface, "Failed to find monitor callbacks"); 01958 return NULL; 01959 } 01960 01961 strcpy(cc_interface->device_name, device_name); 01962 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1); 01963 monitor->parent_id = parent_id; 01964 monitor->core_id = core_id; 01965 monitor->service_offered = cc_data->service; 01966 monitor->private_data = cc_data->private_data; 01967 cc_interface->monitor_type = cc_data->monitor_type; 01968 cc_interface->monitor_class = AST_CC_DEVICE_MONITOR; 01969 monitor->interface = cc_interface; 01970 monitor->available_timer_id = -1; 01971 ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params); 01972 ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %d and parent %d\n", 01973 monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id); 01974 return monitor; 01975 }
static int cc_do_state_change | ( | void * | datap | ) | [static] |
Definition at line 2945 of file ccss.c.
References cc_core_instance::agent, args, AST_CC_AGENT_RESPONSE_FAILURE_INVALID, ast_free, ast_log_dynamic_level, ast_cc_agent::callbacks, CC_CALLER_REQUESTED, cc_state_to_string(), cc_unref(), cc_core_instance::current_state, is_state_change_valid(), ast_cc_agent_callbacks::respond, and state_change_funcs.
Referenced by cc_request_state_change().
02946 { 02947 struct cc_state_change_args *args = datap; 02948 struct cc_core_instance *core_instance; 02949 enum cc_state previous_state; 02950 int res; 02951 02952 ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %d requested. Reason: %s\n", 02953 args->core_id, args->state, args->debug); 02954 02955 core_instance = args->core_instance; 02956 02957 if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) { 02958 ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n", 02959 args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state)); 02960 if (args->state == CC_CALLER_REQUESTED) { 02961 /* 02962 * For out-of-order requests, we need to let the requester know that 02963 * we can't handle the request now. 02964 */ 02965 core_instance->agent->callbacks->respond(core_instance->agent, 02966 AST_CC_AGENT_RESPONSE_FAILURE_INVALID); 02967 } 02968 ast_free(args); 02969 cc_unref(core_instance, "Unref core instance from when it was found earlier"); 02970 return -1; 02971 } 02972 02973 /* We can change to the new state now. */ 02974 previous_state = core_instance->current_state; 02975 core_instance->current_state = args->state; 02976 res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state); 02977 02978 ast_free(args); 02979 cc_unref(core_instance, "Unref since state change has completed"); /* From ao2_find */ 02980 return res; 02981 }
static void cc_extension_monitor_change_is_valid | ( | struct cc_core_instance * | core_instance, | |
unsigned int | parent_id, | |||
const char *const | device_name, | |||
int | is_valid | |||
) | [static] |
Definition at line 1725 of file ccss.c.
References AST_LIST_TRAVERSE, extension_monitor_pvt::child_dialstrings, extension_child_dialstring::device_name, ast_cc_monitor::id, extension_child_dialstring::is_valid, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor::private_data.
Referenced by ast_handle_cc_control_frame(), cancel_available_timer(), cc_monitor_failed(), request_cc(), suspend(), and unsuspend().
01726 { 01727 struct ast_cc_monitor *monitor_iter; 01728 struct extension_monitor_pvt *extension_pvt; 01729 struct extension_child_dialstring *child_dialstring; 01730 01731 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 01732 if (monitor_iter->id == parent_id) { 01733 break; 01734 } 01735 } 01736 01737 if (!monitor_iter) { 01738 return; 01739 } 01740 extension_pvt = monitor_iter->private_data; 01741 01742 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) { 01743 if (!strcmp(child_dialstring->device_name, device_name)) { 01744 child_dialstring->is_valid = is_valid; 01745 break; 01746 } 01747 } 01748 }
static void cc_extension_monitor_destructor | ( | void * | private_data | ) | [static] |
Definition at line 1496 of file ccss.c.
References ast_free, AST_LIST_REMOVE_HEAD, extension_monitor_pvt::child_dialstrings, and cc_monitor_backend::next.
Referenced by cc_monitor_destroy().
01497 { 01498 struct extension_monitor_pvt *extension_pvt = private_data; 01499 struct extension_child_dialstring *child_dialstring; 01500 01501 /* This shouldn't be possible, but I'm paranoid */ 01502 if (!extension_pvt) { 01503 return; 01504 } 01505 01506 while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) { 01507 ast_free(child_dialstring); 01508 } 01509 ast_free(extension_pvt); 01510 }
static struct ast_cc_monitor* cc_extension_monitor_init | ( | const char *const | exten, | |
const char *const | context, | |||
const unsigned int | parent_id | |||
) | [static] |
Definition at line 1764 of file ccss.c.
References ao2_t_alloc, ast_atomic_fetchadd_int(), AST_CC_EXTENSION_MONITOR, ast_log_dynamic_level, AST_MAX_EXTENSION, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_str_strlen(), cc_interface_destroy(), cc_monitor_destroy(), cc_unref(), extension_monitor_pvt_init(), monitor, and str.
Referenced by ast_cc_call_init(), and cc_interfaces_datastore_init().
01765 { 01766 struct ast_str *str = ast_str_alloca(2 * AST_MAX_EXTENSION); 01767 struct ast_cc_interface *cc_interface; 01768 struct ast_cc_monitor *monitor; 01769 01770 ast_str_set(&str, 0, "%s@%s", exten, context); 01771 01772 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy, 01773 "Allocating new ast_cc_interface"))) { 01774 return NULL; 01775 } 01776 01777 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) { 01778 cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface"); 01779 return NULL; 01780 } 01781 01782 if (!(monitor->private_data = extension_monitor_pvt_init())) { 01783 cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor"); 01784 cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface"); 01785 } 01786 01787 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1); 01788 monitor->parent_id = parent_id; 01789 cc_interface->monitor_type = "extension"; 01790 cc_interface->monitor_class = AST_CC_EXTENSION_MONITOR; 01791 strcpy(cc_interface->device_name, ast_str_buffer(str)); 01792 monitor->interface = cc_interface; 01793 ast_log_dynamic_level(cc_logger_level, "Created an extension cc interface for '%s' with id %d and parent %d\n", cc_interface->device_name, monitor->id, monitor->parent_id); 01794 return monitor; 01795 }
static int cc_failed | ( | struct cc_core_instance * | core_instance, | |
struct cc_state_change_args * | args, | |||
enum cc_state | previous_state | |||
) | [static] |
Definition at line 2922 of file ccss.c.
References cc_core_instance::agent, ao2_t_unlink, args, cc_core_instances, cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, and manager_event.
02923 { 02924 manager_event(EVENT_FLAG_CC, "CCFailure", 02925 "CoreID: %d\r\n" 02926 "Caller: %s\r\n" 02927 "Reason: %s\r\n", 02928 core_instance->core_id, core_instance->agent->device_name, args->debug); 02929 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed"); 02930 return 0; 02931 }
static void cc_generic_agent_destructor | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2544 of file ccss.c.
References ast_event_unsubscribe(), ast_free, cc_generic_agent_stop_offer_timer(), ast_cc_agent::private_data, and cc_generic_agent_pvt::sub.
02545 { 02546 struct cc_generic_agent_pvt *agent_pvt = agent->private_data; 02547 02548 if (!agent_pvt) { 02549 /* The agent constructor probably failed. */ 02550 return; 02551 } 02552 02553 cc_generic_agent_stop_offer_timer(agent); 02554 if (agent_pvt->sub) { 02555 agent_pvt->sub = ast_event_unsubscribe(agent_pvt->sub); 02556 } 02557 02558 ast_free(agent_pvt); 02559 }
static int cc_generic_agent_init | ( | struct ast_cc_agent * | agent, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 2340 of file ccss.c.
References ast_calloc, AST_CC_AGENT_SKIP_OFFER, ast_copy_string(), ast_set_flag, ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, ast_channel::macrocontext, ast_channel::macroexten, ast_party_id::name, ast_party_id::number, ast_cc_agent::private_data, S_OR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
02341 { 02342 struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt)); 02343 02344 if (!generic_pvt) { 02345 return -1; 02346 } 02347 02348 generic_pvt->offer_timer_id = -1; 02349 if (chan->caller.id.number.valid && chan->caller.id.number.str) { 02350 ast_copy_string(generic_pvt->cid_num, chan->caller.id.number.str, sizeof(generic_pvt->cid_num)); 02351 } 02352 if (chan->caller.id.name.valid && chan->caller.id.name.str) { 02353 ast_copy_string(generic_pvt->cid_name, chan->caller.id.name.str, sizeof(generic_pvt->cid_name)); 02354 } 02355 ast_copy_string(generic_pvt->exten, S_OR(chan->macroexten, chan->exten), sizeof(generic_pvt->exten)); 02356 ast_copy_string(generic_pvt->context, S_OR(chan->macrocontext, chan->context), sizeof(generic_pvt->context)); 02357 agent->private_data = generic_pvt; 02358 ast_set_flag(agent, AST_CC_AGENT_SKIP_OFFER); 02359 return 0; 02360 }
static int cc_generic_agent_recall | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2528 of file ccss.c.
References ast_cc_agent_caller_busy(), AST_DEVICE_NOT_INUSE, ast_device_state(), AST_DEVICE_UNKNOWN, ast_pthread_create_detached_background, ast_cc_agent::core_id, ast_cc_agent::device_name, and generic_recall().
02529 { 02530 pthread_t clotho; 02531 enum ast_device_state current_state = ast_device_state(agent->device_name); 02532 02533 if (current_state != AST_DEVICE_NOT_INUSE && current_state != AST_DEVICE_UNKNOWN) { 02534 /* We can't try to contact the device right now because he's not available 02535 * Let the core know he's busy. 02536 */ 02537 ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name); 02538 return 0; 02539 } 02540 ast_pthread_create_detached_background(&clotho, NULL, generic_recall, agent); 02541 return 0; 02542 }
static void cc_generic_agent_respond | ( | struct ast_cc_agent * | agent, | |
enum ast_cc_agent_response_reason | reason | |||
) | [static] |
static int cc_generic_agent_start_monitoring | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2456 of file ccss.c.
References ast_assert, AST_DEVICE_NOT_INUSE, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, ast_event_subscribe(), ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_cc_agent::device_name, generic_agent_devstate_cb(), ast_cc_agent::private_data, str, and cc_generic_agent_pvt::sub.
02457 { 02458 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02459 struct ast_str *str = ast_str_alloca(128); 02460 02461 ast_assert(generic_pvt->sub == NULL); 02462 ast_str_set(&str, 0, "Starting to monitor %s device state since it is busy\n", agent->device_name); 02463 02464 if (!(generic_pvt->sub = ast_event_subscribe( 02465 AST_EVENT_DEVICE_STATE, generic_agent_devstate_cb, ast_str_buffer(str), agent, 02466 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, agent->device_name, 02467 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, AST_DEVICE_NOT_INUSE, 02468 AST_EVENT_IE_END))) { 02469 return -1; 02470 } 02471 return 0; 02472 }
static int cc_generic_agent_start_offer_timer | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2374 of file ccss.c.
References ast_assert, ast_get_cc_offer_timer(), ast_log_dynamic_level, ast_sched_thread_add(), ast_cc_agent::cc_params, cc_ref(), cc_sched_thread, ast_cc_agent::core_id, offer_timer_expire(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.
02375 { 02376 int when; 02377 int sched_id; 02378 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02379 02380 ast_assert(cc_sched_thread != NULL); 02381 ast_assert(agent->cc_params != NULL); 02382 02383 when = ast_get_cc_offer_timer(agent->cc_params) * 1000; 02384 ast_log_dynamic_level(cc_logger_level, "Core %d: About to schedule offer timer expiration for %d ms\n", 02385 agent->core_id, when); 02386 if ((sched_id = ast_sched_thread_add(cc_sched_thread, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) { 02387 return -1; 02388 } 02389 generic_pvt->offer_timer_id = sched_id; 02390 return 0; 02391 }
static int cc_generic_agent_status_request | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2414 of file ccss.c.
References ast_cc_agent_status_response(), ast_device_state(), ast_cc_agent::core_id, and ast_cc_agent::device_name.
02415 { 02416 ast_cc_agent_status_response(agent->core_id, ast_device_state(agent->device_name)); 02417 return 0; 02418 }
static int cc_generic_agent_stop_offer_timer | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2393 of file ccss.c.
References ast_sched_thread_del, cc_sched_thread, cc_unref(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.
Referenced by cc_generic_agent_destructor().
02394 { 02395 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02396 02397 if (generic_pvt->offer_timer_id != -1) { 02398 if (!ast_sched_thread_del(cc_sched_thread, generic_pvt->offer_timer_id)) { 02399 cc_unref(agent, "Remove scheduler's reference to the agent"); 02400 } 02401 generic_pvt->offer_timer_id = -1; 02402 } 02403 return 0; 02404 }
static int cc_generic_agent_stop_ringing | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2420 of file ccss.c.
References ast_channel_get_by_name_prefix(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, and ast_cc_agent::device_name.
02421 { 02422 struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name)); 02423 02424 if (!recall_chan) { 02425 return 0; 02426 } 02427 02428 ast_softhangup(recall_chan, AST_SOFTHANGUP_EXPLICIT); 02429 return 0; 02430 }
static int cc_generic_monitor_cancel_available_timer | ( | struct ast_cc_monitor * | monitor, | |
int * | sched_id | |||
) | [static] |
Definition at line 1326 of file ccss.c.
References ast_assert, ast_log_dynamic_level, ast_sched_thread_del, cc_sched_thread, cc_unref(), and monitor.
01327 { 01328 ast_assert(sched_id != NULL); 01329 01330 if (*sched_id == -1) { 01331 return 0; 01332 } 01333 01334 ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n", 01335 monitor->core_id, monitor->interface->device_name); 01336 if (!ast_sched_thread_del(cc_sched_thread, *sched_id)) { 01337 cc_unref(monitor, "Remove scheduler's reference to the monitor"); 01338 } 01339 *sched_id = -1; 01340 return 0; 01341 }
static void cc_generic_monitor_destructor | ( | void * | private_data | ) | [static] |
Definition at line 1343 of file ccss.c.
References ao2_t_unlink, ast_cc_monitor_callee_available(), AST_DEVICE_NOT_INUSE, AST_DEVICE_UNKNOWN, ast_free, AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log_dynamic_level, cc_unref(), generic_monitor_instance::core_id, generic_monitor_pvt::core_id, generic_monitor_instance_list::current_state, generic_monitor_pvt::device_name, find_generic_monitor_instance_list(), generic_monitor_instance_list::fit_for_recall, generic_monitors, generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, generic_monitor_instance::monitoring, and cc_monitor_backend::next.
01344 { 01345 struct generic_monitor_pvt *gen_mon_pvt = private_data; 01346 struct generic_monitor_instance_list *generic_list; 01347 struct generic_monitor_instance *generic_instance; 01348 01349 if (!private_data) { 01350 /* If the private data is NULL, that means that the monitor hasn't even 01351 * been created yet, but that the destructor was called. While this sort 01352 * of behavior is useful for native monitors, with a generic one, there is 01353 * nothing in particular to do. 01354 */ 01355 return; 01356 } 01357 01358 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n", 01359 gen_mon_pvt->core_id, gen_mon_pvt->device_name); 01360 01361 if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) { 01362 /* If there's no generic list, that means that the monitor is being destroyed 01363 * before we actually got to request CC. Not a biggie. Same in the situation 01364 * below if the list traversal should complete without finding an entry. 01365 */ 01366 ast_free((char *)gen_mon_pvt->device_name); 01367 ast_free(gen_mon_pvt); 01368 return; 01369 } 01370 01371 AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) { 01372 if (generic_instance->core_id == gen_mon_pvt->core_id) { 01373 AST_LIST_REMOVE_CURRENT(next); 01374 ast_free(generic_instance); 01375 break; 01376 } 01377 } 01378 AST_LIST_TRAVERSE_SAFE_END; 01379 01380 if (AST_LIST_EMPTY(&generic_list->list)) { 01381 /* No more monitors with this device name exist. Time to unlink this 01382 * list from the container 01383 */ 01384 ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container"); 01385 } else { 01386 /* There are still instances for this particular device. The situation 01387 * may be that we were attempting a CC recall and a failure occurred, perhaps 01388 * on the agent side. If a failure happens here and the device being monitored 01389 * is available, then we need to signal on the first unsuspended instance that 01390 * the device is available for recall. 01391 */ 01392 01393 /* First things first. We don't even want to consider this action if 01394 * the device in question isn't available right now. 01395 */ 01396 if (generic_list->fit_for_recall && (generic_list->current_state == AST_DEVICE_NOT_INUSE || 01397 generic_list->current_state == AST_DEVICE_UNKNOWN)) { 01398 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01399 if (!generic_instance->is_suspended && generic_instance->monitoring) { 01400 ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor " 01401 "availability due to other instance's failure."); 01402 break; 01403 } 01404 } 01405 } 01406 } 01407 cc_unref(generic_list, "Done with generic list in generic monitor destructor"); 01408 ast_free((char *)gen_mon_pvt->device_name); 01409 ast_free(gen_mon_pvt); 01410 }
static int cc_generic_monitor_request_cc | ( | struct ast_cc_monitor * | monitor, | |
int * | available_timer_id | |||
) | [static] |
Definition at line 1194 of file ccss.c.
References ast_calloc, ast_cc_available_timer_expire(), AST_CC_CCBS, AST_CC_CCNL, AST_CC_CCNR, ast_cc_monitor_request_acked(), ast_free, ast_get_ccbs_available_timer(), ast_get_ccnr_available_timer(), AST_LIST_INSERT_TAIL, ast_sched_thread_add(), ast_strdup, cc_ref(), cc_sched_thread, cc_unref(), create_new_generic_list(), find_generic_monitor_instance_list(), generic_monitor_instance_list::fit_for_recall, generic_monitor_instance_list::list, monitor, cc_monitor_backend::next, and service.
01195 { 01196 struct generic_monitor_instance_list *generic_list; 01197 struct generic_monitor_instance *generic_instance; 01198 struct generic_monitor_pvt *gen_mon_pvt; 01199 enum ast_cc_service_type service = monitor->service_offered; 01200 int when; 01201 01202 /* First things first. Native channel drivers will have their private data allocated 01203 * at the time that they tell the core that they can offer CC. Generic is quite a bit 01204 * different, and we wait until this point to allocate our private data. 01205 */ 01206 if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) { 01207 return -1; 01208 } 01209 01210 if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) { 01211 ast_free(gen_mon_pvt); 01212 return -1; 01213 } 01214 01215 gen_mon_pvt->core_id = monitor->core_id; 01216 01217 monitor->private_data = gen_mon_pvt; 01218 01219 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) { 01220 if (!(generic_list = create_new_generic_list(monitor))) { 01221 return -1; 01222 } 01223 } 01224 01225 if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) { 01226 /* The generic monitor destructor will take care of the appropriate 01227 * deallocations 01228 */ 01229 cc_unref(generic_list, "Generic monitor instance failed to allocate"); 01230 return -1; 01231 } 01232 generic_instance->core_id = monitor->core_id; 01233 generic_instance->monitoring = 1; 01234 AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next); 01235 when = service == AST_CC_CCBS ? ast_get_ccbs_available_timer(monitor->interface->config_params) : 01236 ast_get_ccnr_available_timer(monitor->interface->config_params); 01237 01238 *available_timer_id = ast_sched_thread_add(cc_sched_thread, when * 1000, 01239 ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference")); 01240 if (*available_timer_id == -1) { 01241 cc_unref(monitor, "Failed to schedule available timer. (monitor)"); 01242 cc_unref(generic_list, "Failed to schedule available timer. (generic_list)"); 01243 return -1; 01244 } 01245 /* If the new instance was created as CCNR, then that means this device is not currently 01246 * fit for recall even if it previously was. 01247 */ 01248 if (service == AST_CC_CCNR || service == AST_CC_CCNL) { 01249 generic_list->fit_for_recall = 0; 01250 } 01251 ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.", 01252 monitor->interface->device_name); 01253 cc_unref(generic_list, "Finished with monitor instance reference in request cc callback"); 01254 return 0; 01255 }
static int cc_generic_monitor_suspend | ( | struct ast_cc_monitor * | monitor | ) | [static] |
Definition at line 1257 of file ccss.c.
References ast_cc_monitor_callee_available(), AST_DEVICE_NOT_INUSE, ast_device_state(), AST_DEVICE_UNKNOWN, AST_LIST_TRAVERSE, cc_unref(), generic_monitor_instance::core_id, find_generic_monitor_instance_list(), generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, monitor, and cc_monitor_backend::next.
01258 { 01259 struct generic_monitor_instance_list *generic_list; 01260 struct generic_monitor_instance *generic_instance; 01261 enum ast_device_state state = ast_device_state(monitor->interface->device_name); 01262 01263 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) { 01264 return -1; 01265 } 01266 01267 /* First we need to mark this particular monitor as being suspended. */ 01268 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01269 if (generic_instance->core_id == monitor->core_id) { 01270 generic_instance->is_suspended = 1; 01271 break; 01272 } 01273 } 01274 01275 /* If the device being suspended is currently in use, then we don't need to 01276 * take any further actions 01277 */ 01278 if (state != AST_DEVICE_NOT_INUSE && state != AST_DEVICE_UNKNOWN) { 01279 cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list."); 01280 return 0; 01281 } 01282 01283 /* If the device is not in use, though, then it may be possible to report the 01284 * device's availability using a different monitor which is monitoring the 01285 * same device 01286 */ 01287 01288 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01289 if (!generic_instance->is_suspended) { 01290 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available"); 01291 break; 01292 } 01293 } 01294 cc_unref(generic_list, "Done with generic list in suspend callback"); 01295 return 0; 01296 }
static int cc_generic_monitor_unsuspend | ( | struct ast_cc_monitor * | monitor | ) | [static] |
Definition at line 1298 of file ccss.c.
References ast_cc_monitor_callee_available(), AST_DEVICE_NOT_INUSE, ast_device_state(), AST_DEVICE_UNKNOWN, AST_LIST_TRAVERSE, cc_unref(), generic_monitor_instance::core_id, find_generic_monitor_instance_list(), generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, monitor, generic_monitor_instance::monitoring, and cc_monitor_backend::next.
01299 { 01300 struct generic_monitor_instance *generic_instance; 01301 struct generic_monitor_instance_list *generic_list = find_generic_monitor_instance_list(monitor->interface->device_name); 01302 enum ast_device_state state = ast_device_state(monitor->interface->device_name); 01303 01304 if (!generic_list) { 01305 return -1; 01306 } 01307 /* If the device is currently available, we can immediately announce 01308 * its availability 01309 */ 01310 if (state == AST_DEVICE_NOT_INUSE || state == AST_DEVICE_UNKNOWN) { 01311 ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available"); 01312 } 01313 01314 /* In addition, we need to mark this generic_monitor_instance as not being suspended anymore */ 01315 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01316 if (generic_instance->core_id == monitor->core_id) { 01317 generic_instance->is_suspended = 0; 01318 generic_instance->monitoring = 1; 01319 break; 01320 } 01321 } 01322 cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend"); 01323 return 0; 01324 }
static void cc_interface_destroy | ( | void * | data | ) | [static] |
Definition at line 1412 of file ccss.c.
References ast_cc_config_params_destroy(), ast_log_dynamic_level, ast_cc_interface::config_params, and ast_cc_interface::device_name.
Referenced by cc_device_monitor_init(), and cc_extension_monitor_init().
01413 { 01414 struct ast_cc_interface *interface = data; 01415 ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name); 01416 ast_cc_config_params_destroy(interface->config_params); 01417 }
static void cc_interface_tree_destroy | ( | void * | data | ) | [static] |
Definition at line 1533 of file ccss.c.
References AST_LIST_HEAD_DESTROY, AST_LIST_REMOVE_HEAD, cc_unref(), monitor, and cc_monitor_backend::next.
Referenced by cc_interfaces_datastore_init().
01534 { 01535 struct cc_monitor_tree *cc_interface_tree = data; 01536 struct ast_cc_monitor *monitor; 01537 while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) { 01538 if (monitor->callbacks) { 01539 monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id); 01540 } 01541 cc_unref(monitor, "Destroying all monitors"); 01542 } 01543 AST_LIST_HEAD_DESTROY(cc_interface_tree); 01544 }
static int cc_interfaces_datastore_init | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 1813 of file ccss.c.
References ao2_t_alloc, ast_atomic_fetchadd_int(), ast_calloc, ast_cc_request_is_within_limits(), ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_free, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, cc_extension_monitor_init(), cc_interface_tree_destroy(), cc_ref(), cc_unref(), ast_channel::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, dialed_cc_interfaces_info, ast_channel::exten, ast_datastore::inheritance, ast_channel::macrocontext, ast_channel::macroexten, monitor, cc_monitor_backend::next, and S_OR.
Referenced by ast_cc_call_init().
01813 { 01814 struct dialed_cc_interfaces *interfaces; 01815 struct ast_cc_monitor *monitor; 01816 struct ast_datastore *dial_cc_datastore; 01817 01818 /*XXX This may be a bit controversial. In an attempt to not allocate 01819 * extra resources, I make sure that a future request will be within 01820 * limits. The problem here is that it is reasonable to think that 01821 * even if we're not within the limits at this point, we may be by 01822 * the time the requestor will have made his request. This may be 01823 * deleted at some point. 01824 */ 01825 if (!ast_cc_request_is_within_limits()) { 01826 return 0; 01827 } 01828 01829 if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) { 01830 return -1; 01831 } 01832 01833 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten), S_OR(chan->macrocontext, chan->context), 0))) { 01834 ast_free(interfaces); 01835 return -1; 01836 } 01837 01838 if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) { 01839 cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor"); 01840 ast_free(interfaces); 01841 return -1; 01842 } 01843 01844 if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy, 01845 "Allocate monitor tree"))) { 01846 ast_datastore_free(dial_cc_datastore); 01847 cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor"); 01848 ast_free(interfaces); 01849 return -1; 01850 } 01851 01852 /* Finally, all that allocation is done... */ 01853 AST_LIST_HEAD_INIT(interfaces->interface_tree); 01854 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next); 01855 cc_ref(monitor, "List's reference to extension monitor"); 01856 dial_cc_datastore->data = interfaces; 01857 dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER; 01858 interfaces->dial_parent_id = monitor->id; 01859 interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1); 01860 interfaces->is_original_caller = 1; 01861 ast_channel_lock(chan); 01862 ast_channel_datastore_add(chan, dial_cc_datastore); 01863 ast_channel_unlock(chan); 01864 cc_unref(monitor, "Unreffing allocation's reference"); 01865 return 0; 01866 }
static void cc_monitor_destroy | ( | void * | data | ) | [static] |
Definition at line 1512 of file ccss.c.
References AST_CC_EXTENSION_MONITOR, ast_free, ast_log_dynamic_level, cc_extension_monitor_destructor(), cc_unref(), and monitor.
Referenced by cc_device_monitor_init(), and cc_extension_monitor_init().
01513 { 01514 struct ast_cc_monitor *monitor = data; 01515 /* During the monitor creation process, it is possible for this 01516 * function to be called prior to when callbacks are assigned 01517 * to the monitor. Also, extension monitors do not have callbacks 01518 * assigned to them, so we wouldn't want to segfault when we try 01519 * to destroy one of them. 01520 */ 01521 ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n", 01522 monitor->core_id, monitor->interface->device_name); 01523 if (monitor->interface->monitor_class == AST_CC_EXTENSION_MONITOR) { 01524 cc_extension_monitor_destructor(monitor->private_data); 01525 } 01526 if (monitor->callbacks) { 01527 monitor->callbacks->destructor(monitor->private_data); 01528 } 01529 cc_unref(monitor->interface, "Unreffing tree's reference to interface"); 01530 ast_free(monitor->dialstring); 01531 }
static int cc_monitor_failed | ( | void * | data | ) | [static] |
Definition at line 3551 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cc_failed(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, ast_cc_monitor::core_id, ast_cc_monitor_failure_data::core_id, ast_cc_monitor_failure_data::debug, ast_cc_interface::device_name, ast_cc_monitor_failure_data::device_name, EVENT_FLAG_CC, find_cc_core_instance(), has_device_monitors(), ast_cc_monitor::interface, manager_event, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor::parent_id.
Referenced by ast_cc_monitor_failed().
03552 { 03553 struct ast_cc_monitor_failure_data *failure_data = data; 03554 struct cc_core_instance *core_instance; 03555 struct ast_cc_monitor *monitor_iter; 03556 03557 core_instance = find_cc_core_instance(failure_data->core_id); 03558 if (!core_instance) { 03559 /* Core instance no longer exists or invalid core_id. */ 03560 ast_log_dynamic_level(cc_logger_level, 03561 "Core %d: Could not find core instance for device %s '%s'\n", 03562 failure_data->core_id, failure_data->device_name, failure_data->debug); 03563 ast_free((char *) failure_data->device_name); 03564 ast_free((char *) failure_data->debug); 03565 ast_free(failure_data); 03566 return -1; 03567 } 03568 03569 AST_LIST_LOCK(core_instance->monitors); 03570 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 03571 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 03572 if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) { 03573 AST_LIST_REMOVE_CURRENT(next); 03574 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 03575 monitor_iter->interface->device_name, 1); 03576 monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id); 03577 manager_event(EVENT_FLAG_CC, "CCMonitorFailed", 03578 "CoreID: %d\r\n" 03579 "Callee: %s\r\n", 03580 monitor_iter->core_id, monitor_iter->interface->device_name); 03581 cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference."); 03582 } 03583 } 03584 } 03585 AST_LIST_TRAVERSE_SAFE_END; 03586 03587 if (!has_device_monitors(core_instance)) { 03588 ast_cc_failed(core_instance->core_id, "All monitors have failed\n"); 03589 } 03590 AST_LIST_UNLOCK(core_instance->monitors); 03591 cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n"); 03592 03593 ast_free((char *) failure_data->device_name); 03594 ast_free((char *) failure_data->debug); 03595 ast_free(failure_data); 03596 return 0; 03597 }
static int cc_offer | ( | const int | core_id, | |
const char *const | debug, | |||
... | ||||
) | [static] |
Definition at line 3395 of file ccss.c.
References CC_CALLER_OFFERED, and cc_request_state_change().
Referenced by ast_cc_offer().
03396 { 03397 va_list ap; 03398 int res; 03399 03400 va_start(ap, debug); 03401 res = cc_request_state_change(CC_CALLER_OFFERED, core_id, debug, ap); 03402 va_end(ap); 03403 return res; 03404 }
static int cc_party_b_free | ( | void * | data | ) | [static] |
Definition at line 3697 of file ccss.c.
References cc_core_instance::agent, ast_cc_agent::callbacks, cc_unref(), and ast_cc_agent_callbacks::party_b_free.
Referenced by ast_cc_monitor_party_b_free().
03698 { 03699 struct cc_core_instance *core_instance = data; 03700 int res = 0; 03701 03702 if (core_instance->agent->callbacks->party_b_free) { 03703 res = core_instance->agent->callbacks->party_b_free(core_instance->agent); 03704 } 03705 cc_unref(core_instance, "Party B free finished. Unref core_instance"); 03706 return res; 03707 }
static void cc_recall_ds_destroy | ( | void * | data | ) | [static] |
Definition at line 3047 of file ccss.c.
References ast_free, cc_unref(), and cc_recall_ds_data::interface_tree.
03048 { 03049 struct cc_recall_ds_data *recall_data = data; 03050 recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree"); 03051 ast_free(recall_data); 03052 }
static void* cc_recall_ds_duplicate | ( | void * | data | ) | [static] |
Definition at line 3033 of file ccss.c.
References ast_calloc, cc_ref(), cc_recall_ds_data::core_id, and cc_recall_ds_data::interface_tree.
03034 { 03035 struct cc_recall_ds_data *old_data = data; 03036 struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data)); 03037 03038 if (!new_data) { 03039 return NULL; 03040 } 03041 new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate"); 03042 new_data->core_id = old_data->core_id; 03043 new_data->nested = 1; 03044 return new_data; 03045 }
static int cc_recalling | ( | struct cc_core_instance * | core_instance, | |
struct cc_state_change_args * | args, | |||
enum cc_state | previous_state | |||
) | [static] |
Definition at line 2898 of file ccss.c.
References cc_core_instance::agent, cancel_available_timer(), cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, and manager_event.
02899 { 02900 /* Both caller and callee are available, call agent's recall callback 02901 */ 02902 cancel_available_timer(core_instance); 02903 manager_event(EVENT_FLAG_CC, "CCCallerRecalling", 02904 "CoreID: %d\r\n" 02905 "Caller: %s\r\n", 02906 core_instance->core_id, core_instance->agent->device_name); 02907 return 0; 02908 }
static void* cc_ref | ( | void * | obj, | |
const char * | debug | |||
) | [inline, static] |
Definition at line 101 of file ccss.c.
References ao2_t_ref.
Referenced by ast_cc_agent_callback(), ast_cc_call_init(), ast_cc_get_monitor_by_recall_core_id(), ast_handle_cc_control_frame(), ast_setup_cc_recall_datastore(), cc_core_init_instance(), cc_generic_agent_start_offer_timer(), cc_generic_monitor_request_cc(), cc_interfaces_datastore_init(), cc_recall_ds_duplicate(), dialed_cc_interfaces_duplicate(), and generic_agent_devstate_cb().
static int cc_request_state_change | ( | enum cc_state | state, | |
const int | core_id, | |||
const char * | debug, | |||
va_list | ap | |||
) | [static] |
Definition at line 2983 of file ccss.c.
References args, ast_calloc, ast_free, ast_log_dynamic_level, ast_taskprocessor_push(), cc_core_taskprocessor, cc_do_state_change(), cc_unref(), cc_core_instance::core_id, cc_state_change_args::core_instance, dummy(), and find_cc_core_instance().
Referenced by ast_cc_agent_accept_request(), ast_cc_agent_caller_available(), ast_cc_agent_caller_busy(), ast_cc_agent_recalling(), ast_cc_completed(), ast_cc_failed(), ast_cc_monitor_callee_available(), ast_cc_monitor_request_acked(), and cc_offer().
02984 { 02985 int res; 02986 int debuglen; 02987 char dummy[1]; 02988 va_list aq; 02989 struct cc_core_instance *core_instance; 02990 struct cc_state_change_args *args; 02991 /* This initial call to vsnprintf is simply to find what the 02992 * size of the string needs to be 02993 */ 02994 va_copy(aq, ap); 02995 /* We add 1 to the result since vsnprintf's return does not 02996 * include the terminating null byte 02997 */ 02998 debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1; 02999 va_end(aq); 03000 03001 if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) { 03002 return -1; 03003 } 03004 03005 core_instance = find_cc_core_instance(core_id); 03006 if (!core_instance) { 03007 ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n", 03008 core_id); 03009 ast_free(args); 03010 return -1; 03011 } 03012 03013 args->core_instance = core_instance; 03014 args->state = state; 03015 args->core_id = core_id; 03016 vsnprintf(args->debug, debuglen, debug, ap); 03017 03018 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_do_state_change, args); 03019 if (res) { 03020 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03021 ast_free(args); 03022 } 03023 return res; 03024 }
static const char* cc_service_to_string | ( | enum ast_cc_service_type | service | ) | [static] |
Definition at line 369 of file ccss.c.
References cc_service_to_string_map.
Referenced by ast_handle_cc_control_frame(), and cc_cli_print_monitor_stats().
00370 { 00371 return cc_service_to_string_map[service].service_string; 00372 }
static const char* cc_state_to_string | ( | enum cc_state | state | ) | [static] |
Definition at line 364 of file ccss.c.
References cc_state_to_string_map.
Referenced by cc_do_state_change(), and print_stats_cb().
00365 { 00366 return cc_state_to_string_map[state].state_string; 00367 }
static int cc_status_request | ( | void * | data | ) | [static] |
Definition at line 3634 of file ccss.c.
References cc_core_instance::agent, ast_cc_agent::callbacks, cc_unref(), and ast_cc_agent_callbacks::status_request.
Referenced by ast_cc_monitor_status_request().
03635 { 03636 struct cc_core_instance *core_instance= data; 03637 int res; 03638 03639 res = core_instance->agent->callbacks->status_request(core_instance->agent); 03640 cc_unref(core_instance, "Status request finished. Unref core instance"); 03641 return res; 03642 }
static int cc_status_response | ( | void * | data | ) | [static] |
Definition at line 3730 of file ccss.c.
References args, AST_CC_DEVICE_MONITOR, ast_device_state(), ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_unref(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor_callbacks::status_response.
Referenced by ast_cc_agent_status_response().
03731 { 03732 struct cc_status_response_args *args = data; 03733 struct cc_core_instance *core_instance = args->core_instance; 03734 struct ast_cc_monitor *monitor_iter; 03735 enum ast_device_state devstate = args->devstate; 03736 03737 ast_free(args); 03738 03739 AST_LIST_LOCK(core_instance->monitors); 03740 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 03741 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR && 03742 monitor_iter->callbacks->status_response) { 03743 monitor_iter->callbacks->status_response(monitor_iter, devstate); 03744 } 03745 } 03746 AST_LIST_UNLOCK(core_instance->monitors); 03747 cc_unref(core_instance, "Status response finished. Unref core instance"); 03748 return 0; 03749 }
static int cc_stop_ringing | ( | void * | data | ) | [static] |
Definition at line 3660 of file ccss.c.
References cc_core_instance::agent, ast_cc_monitor_request_acked(), ast_cc_agent::callbacks, cc_unref(), cc_core_instance::core_id, ast_cc_agent::device_name, and ast_cc_agent_callbacks::stop_ringing.
Referenced by ast_cc_monitor_stop_ringing().
03661 { 03662 struct cc_core_instance *core_instance = data; 03663 int res = 0; 03664 03665 if (core_instance->agent->callbacks->stop_ringing) { 03666 res = core_instance->agent->callbacks->stop_ringing(core_instance->agent); 03667 } 03668 /* If an agent is being asked to stop ringing, then he needs to be prepared if for 03669 * whatever reason he needs to be called back again. The proper state to be in to 03670 * detect such a circumstance is the CC_ACTIVE state. 03671 * 03672 * We get to this state using the slightly unintuitive method of calling 03673 * ast_cc_monitor_request_acked because it gets us to the proper state. 03674 */ 03675 ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.", 03676 core_instance->agent->device_name); 03677 cc_unref(core_instance, "Stop ringing finished. Unref core_instance"); 03678 return res; 03679 }
static void cc_unique_append | ( | struct ast_str * | str, | |
const char * | dialstring | |||
) | [static] |
Definition at line 3213 of file ccss.c.
References AST_CHANNEL_NAME, ast_str_append(), ast_str_buffer(), ast_strlen_zero(), and str.
Referenced by build_cc_interfaces_chanvar().
03214 { 03215 char dialstring_search[AST_CHANNEL_NAME]; 03216 03217 if (ast_strlen_zero(dialstring)) { 03218 /* No dialstring to append. */ 03219 return; 03220 } 03221 snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&'); 03222 if (strstr(ast_str_buffer(str), dialstring_search)) { 03223 return; 03224 } 03225 ast_str_append(&str, 0, "%s", dialstring_search); 03226 }
static void* cc_unref | ( | void * | obj, | |
const char * | debug | |||
) | [inline, static] |
Definition at line 107 of file ccss.c.
References ao2_t_ref.
Referenced by ast_cc_agent_callback(), ast_cc_agent_status_response(), ast_cc_available_timer_expire(), ast_cc_call_init(), ast_cc_get_monitor_by_recall_core_id(), ast_cc_monitor_party_b_free(), ast_cc_monitor_status_request(), ast_cc_monitor_stop_ringing(), ast_handle_cc_control_frame(), ast_setup_cc_recall_datastore(), cancel_available_timer(), cc_agent_init(), cc_core_init_instance(), cc_core_instance_destructor(), cc_device_monitor_init(), cc_do_state_change(), cc_extension_monitor_init(), cc_generic_agent_stop_offer_timer(), cc_generic_monitor_cancel_available_timer(), cc_generic_monitor_destructor(), cc_generic_monitor_request_cc(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), cc_interface_tree_destroy(), cc_interfaces_datastore_init(), cc_monitor_destroy(), cc_monitor_failed(), cc_party_b_free(), cc_recall_ds_destroy(), cc_request_state_change(), cc_status_request(), cc_status_response(), cc_stop_ringing(), cccancel_exec(), ccreq_exec(), complete_core_id(), create_new_generic_list(), dialed_cc_interfaces_destroy(), generic_agent_devstate_cb(), generic_agent_devstate_unsubscribe(), generic_monitor_devstate_tp_cb(), offer_timer_expire(), request_cc(), suspend(), and unsuspend().
static int cccancel_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 3958 of file ccss.c.
References cc_core_instance::agent, ao2_t_callback_data, ast_cc_failed(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_log(), ast_cc_agent::callbacks, cc_core_instances, cc_unref(), cc_core_instance::core_id, LOG_WARNING, match_agent(), MATCH_REQUEST, and ast_cc_agent_callbacks::type.
Referenced by ast_cc_init().
03959 { 03960 struct cc_core_instance *core_instance; 03961 char device_name[AST_CHANNEL_NAME]; 03962 unsigned long match_flags; 03963 int res; 03964 03965 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 03966 03967 match_flags = MATCH_REQUEST; 03968 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) { 03969 ast_log(LOG_WARNING, "Cannot find CC transaction to cancel for caller %s\n", device_name); 03970 return -1; 03971 } 03972 03973 if (strcmp(core_instance->agent->callbacks->type, "generic")) { 03974 ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calles with a generic agent\n"); 03975 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel"); 03976 return -1; 03977 } 03978 res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s", 03979 core_instance->core_id, device_name); 03980 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel"); 03981 return res; 03982 }
static int ccreq_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 3915 of file ccss.c.
References cc_core_instance::agent, ao2_t_callback_data, ast_cc_agent_accept_request(), ast_cc_failed(), ast_cc_request_is_within_limits(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_log_dynamic_level, ast_cc_agent::callbacks, cc_core_instances, cc_unref(), cc_core_instance::core_id, match_agent(), MATCH_NO_REQUEST, pbx_builtin_setvar_helper(), and ast_cc_agent_callbacks::type.
Referenced by ast_cc_init().
03916 { 03917 struct cc_core_instance *core_instance; 03918 char device_name[AST_CHANNEL_NAME]; 03919 unsigned long match_flags; 03920 int res; 03921 03922 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 03923 03924 match_flags = MATCH_NO_REQUEST; 03925 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) { 03926 ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name); 03927 return -1; 03928 } 03929 03930 ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n", 03931 core_instance->core_id, device_name); 03932 03933 if (strcmp(core_instance->agent->callbacks->type, "generic")) { 03934 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n", 03935 core_instance->core_id); 03936 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL"); 03937 cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent"); 03938 return 0; 03939 } 03940 03941 if (!ast_cc_request_is_within_limits()) { 03942 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n", 03943 core_instance->core_id); 03944 ast_cc_failed(core_instance->core_id, "Too many CC requests\n"); 03945 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL"); 03946 cc_unref(core_instance, "Unref core_instance since too many CC requests"); 03947 return 0; 03948 } 03949 03950 res = ast_cc_agent_accept_request(core_instance->core_id, "CallCompletionRequest called by caller %s for core_id %d", device_name, core_instance->core_id); 03951 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS"); 03952 cc_unref(core_instance, "Done with CallCompletionRequest"); 03953 return res; 03954 }
static void check_callback_sanity | ( | const struct ast_cc_agent_callbacks * | callbacks | ) | [static] |
Definition at line 2203 of file ccss.c.
References ast_assert, cc_monitor_backend::callbacks, and ast_cc_monitor_callbacks::destructor.
Referenced by cc_agent_init().
02204 { 02205 ast_assert(callbacks->init != NULL); 02206 ast_assert(callbacks->start_offer_timer != NULL); 02207 ast_assert(callbacks->stop_offer_timer != NULL); 02208 ast_assert(callbacks->respond != NULL); 02209 ast_assert(callbacks->status_request != NULL); 02210 ast_assert(callbacks->start_monitoring != NULL); 02211 ast_assert(callbacks->callee_available != NULL); 02212 ast_assert(callbacks->destructor != NULL); 02213 }
static char* complete_core_id | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 4144 of file ccss.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, cc_core_instances, cc_unref(), and cc_core_instance::core_id.
Referenced by handle_cc_kill().
04145 { 04146 int which = 0; 04147 int wordlen = strlen(word); 04148 char *ret = NULL; 04149 struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0); 04150 struct cc_core_instance *core_instance; 04151 04152 for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance")); 04153 cc_unref(core_instance, "CLI tab completion iteration")) { 04154 char core_id_str[20]; 04155 snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id); 04156 if (!strncmp(word, core_id_str, wordlen) && ++which > state) { 04157 ret = ast_strdup(core_id_str); 04158 cc_unref(core_instance, "Found a matching core ID for CLI tab-completion"); 04159 break; 04160 } 04161 } 04162 ao2_iterator_destroy(&core_iter); 04163 04164 return ret; 04165 }
static long count_agents | ( | const char *const | caller, | |
const int | core_id_exception | |||
) | [static] |
Definition at line 2188 of file ccss.c.
References ao2_t_callback_data, ast_log_dynamic_level, cc_core_instances, count_agents_cb_data::core_id_exception, count_agents_cb_data::count, count_agents_cb(), and OBJ_NODATA.
Referenced by agents_show(), agents_show_online(), and cc_core_init_instance().
02189 { 02190 struct count_agents_cb_data data = {.core_id_exception = core_id_exception,}; 02191 02192 ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents"); 02193 ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count); 02194 return data.count; 02195 }
static int count_agents_cb | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 487 of file ccss.c.
References cc_core_instance::agent, ast_log_dynamic_level, CC_CALLER_REQUESTED, cc_core_instance::core_id, count_agents_cb_data::core_id_exception, count_agents_cb_data::count, cc_core_instance::current_state, ast_cc_agent::device_name, and name.
Referenced by count_agents().
00488 { 00489 struct cc_core_instance *core_instance = obj; 00490 const char *name = arg; 00491 struct count_agents_cb_data *cb_data = data; 00492 00493 if (cb_data->core_id_exception == core_instance->core_id) { 00494 ast_log_dynamic_level(cc_logger_level, "Found agent with core_id %d but not counting it toward total\n", core_instance->core_id); 00495 return 0; 00496 } 00497 00498 if (core_instance->current_state >= CC_CALLER_REQUESTED && !strcmp(core_instance->agent->device_name, name)) { 00499 cb_data->count++; 00500 } 00501 return 0; 00502 }
static int count_monitors_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 3990 of file ccss.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, count_monitors_cb_data::count, ast_cc_interface::device_name, count_monitors_cb_data::device_name, ast_cc_monitor::interface, ast_cc_interface::monitor_type, count_monitors_cb_data::monitor_type, cc_core_instance::monitors, and cc_monitor_backend::next.
Referenced by ast_cc_monitor_count().
03991 { 03992 struct cc_core_instance *core_instance = obj; 03993 struct count_monitors_cb_data *cb_data = arg; 03994 const char *device_name = cb_data->device_name; 03995 const char *monitor_type = cb_data->monitor_type; 03996 struct ast_cc_monitor *monitor_iter; 03997 03998 AST_LIST_LOCK(core_instance->monitors); 03999 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 04000 if (!strcmp(monitor_iter->interface->device_name, device_name) && 04001 !strcmp(monitor_iter->interface->monitor_type, monitor_type)) { 04002 cb_data->count++; 04003 break; 04004 } 04005 } 04006 AST_LIST_UNLOCK(core_instance->monitors); 04007 return 0; 04008 }
static struct generic_monitor_instance_list* create_new_generic_list | ( | struct ast_cc_monitor * | monitor | ) | [static] |
Definition at line 1081 of file ccss.c.
References ao2_t_alloc, ao2_t_link, ast_device_state(), AST_EVENT_DEVICE_STATE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, ast_event_subscribe(), ast_strdup, cc_unref(), generic_monitor_devstate_cb(), generic_monitor_instance_list_destructor(), generic_monitors, and monitor.
Referenced by cc_generic_monitor_request_cc().
01082 { 01083 struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list), 01084 generic_monitor_instance_list_destructor, "allocate generic monitor instance list"); 01085 01086 if (!generic_list) { 01087 return NULL; 01088 } 01089 01090 if (!(generic_list->device_name = ast_strdup(monitor->interface->device_name))) { 01091 cc_unref(generic_list, "Failed to strdup the monitor's device name"); 01092 return NULL; 01093 } 01094 01095 if (!(generic_list->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, generic_monitor_devstate_cb, 01096 "Requesting CC", NULL, AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, 01097 monitor->interface->device_name, AST_EVENT_IE_END))) { 01098 cc_unref(generic_list, "Failed to subscribe to device state"); 01099 return NULL; 01100 } 01101 generic_list->current_state = ast_device_state(monitor->interface->device_name); 01102 ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list"); 01103 return generic_list; 01104 }
static void dialed_cc_interfaces_destroy | ( | void * | data | ) | [static] |
Definition at line 1619 of file ccss.c.
References ast_free, cc_unref(), and dialed_cc_interfaces::interface_tree.
01620 { 01621 struct dialed_cc_interfaces *cc_interfaces = data; 01622 cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree"); 01623 ast_free(cc_interfaces); 01624 }
static void* dialed_cc_interfaces_duplicate | ( | void * | data | ) | [static] |
Definition at line 1639 of file ccss.c.
References ast_calloc, cc_ref(), dialed_cc_interfaces::core_id, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces::ignore, and dialed_cc_interfaces::interface_tree.
01640 { 01641 struct dialed_cc_interfaces *old_cc_interfaces = data; 01642 struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces)); 01643 if (!new_cc_interfaces) { 01644 return NULL; 01645 } 01646 new_cc_interfaces->ignore = old_cc_interfaces->ignore; 01647 new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id; 01648 new_cc_interfaces->is_original_caller = 0; 01649 cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree"); 01650 new_cc_interfaces->core_id = old_cc_interfaces->core_id; 01651 new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree; 01652 return new_cc_interfaces; 01653 }
static struct extension_monitor_pvt* extension_monitor_pvt_init | ( | void | ) | [static] |
Definition at line 1670 of file ccss.c.
References ast_calloc, and AST_LIST_HEAD_INIT_NOLOCK.
Referenced by cc_extension_monitor_init().
01671 { 01672 struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt)); 01673 if (!ext_pvt) { 01674 return NULL; 01675 } 01676 AST_LIST_HEAD_INIT_NOLOCK(&ext_pvt->child_dialstrings); 01677 return ext_pvt; 01678 }
static struct ast_cc_agent_callbacks* find_agent_callbacks | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 947 of file ccss.c.
References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, ast_channel_get_cc_agent_type(), ast_channel_get_cc_config_params(), ast_copy_string(), ast_get_cc_agent_policy(), ast_log_dynamic_level, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, cc_agent_backend::callbacks, cc_monitor_backend::callbacks, cc_monitor_backend::next, ast_cc_agent_callbacks::type, and type.
Referenced by cc_agent_init().
00948 { 00949 struct cc_agent_backend *backend; 00950 const struct ast_cc_agent_callbacks *callbacks = NULL; 00951 struct ast_cc_config_params *cc_params; 00952 char type[32]; 00953 00954 cc_params = ast_channel_get_cc_config_params(chan); 00955 if (!cc_params) { 00956 return NULL; 00957 } 00958 switch (ast_get_cc_agent_policy(cc_params)) { 00959 case AST_CC_AGENT_GENERIC: 00960 ast_copy_string(type, "generic", sizeof(type)); 00961 break; 00962 case AST_CC_AGENT_NATIVE: 00963 ast_channel_get_cc_agent_type(chan, type, sizeof(type)); 00964 break; 00965 default: 00966 ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n"); 00967 return NULL; 00968 } 00969 00970 AST_RWLIST_RDLOCK(&cc_agent_backends); 00971 AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) { 00972 if (!strcmp(backend->callbacks->type, type)) { 00973 ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type); 00974 callbacks = backend->callbacks; 00975 break; 00976 } 00977 } 00978 AST_RWLIST_UNLOCK(&cc_agent_backends); 00979 return callbacks; 00980 }
static struct cc_core_instance* find_cc_core_instance | ( | const int | core_id | ) | [static] |
Definition at line 388 of file ccss.c.
References ao2_t_find, cc_core_instances, cc_core_instance::core_id, and OBJ_POINTER.
Referenced by ast_cc_agent_status_response(), ast_cc_get_monitor_by_recall_core_id(), ast_cc_monitor_party_b_free(), ast_cc_monitor_status_request(), ast_cc_monitor_stop_ringing(), ast_handle_cc_control_frame(), ast_setup_cc_recall_datastore(), cc_monitor_failed(), and cc_request_state_change().
00389 { 00390 struct cc_core_instance finder = {.core_id = core_id,}; 00391 00392 return ao2_t_find(cc_core_instances, &finder, OBJ_POINTER, "Finding a core_instance"); 00393 }
static struct generic_monitor_instance_list* find_generic_monitor_instance_list | ( | const char *const | device_name | ) | [static] |
Definition at line 1061 of file ccss.c.
References ao2_t_find, generic_monitor_instance_list::device_name, generic_monitors, and OBJ_POINTER.
Referenced by cc_generic_monitor_destructor(), cc_generic_monitor_request_cc(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), and generic_monitor_devstate_tp_cb().
01062 { 01063 struct generic_monitor_instance_list finder = {.device_name = device_name}; 01064 01065 return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list"); 01066 }
static struct ast_cc_monitor_callbacks* find_monitor_callbacks | ( | const char *const | type | ) | [static] |
Definition at line 878 of file ccss.c.
References ast_log_dynamic_level, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, cc_monitor_backend::callbacks, cc_monitor_backend::next, and ast_cc_monitor_callbacks::type.
Referenced by call_destructor_with_no_monitor(), and cc_device_monitor_init().
00879 { 00880 struct cc_monitor_backend *backend; 00881 const struct ast_cc_monitor_callbacks *callbacks = NULL; 00882 00883 AST_RWLIST_RDLOCK(&cc_monitor_backends); 00884 AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) { 00885 if (!strcmp(backend->callbacks->type, type)) { 00886 ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type); 00887 callbacks = backend->callbacks; 00888 break; 00889 } 00890 } 00891 AST_RWLIST_UNLOCK(&cc_monitor_backends); 00892 return callbacks; 00893 }
static void generic_agent_devstate_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 2444 of file ccss.c.
References ast_cc_agent_caller_available(), ast_taskprocessor_push(), cc_core_taskprocessor, cc_ref(), cc_unref(), ast_cc_agent::core_id, ast_cc_agent::device_name, and generic_agent_devstate_unsubscribe().
Referenced by cc_generic_agent_start_monitoring().
02445 { 02446 struct ast_cc_agent *agent = userdata; 02447 02448 /* We can't unsubscribe from device state events here because it causes a deadlock */ 02449 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_agent_devstate_unsubscribe, 02450 cc_ref(agent, "ref agent for device state unsubscription"))) { 02451 cc_unref(agent, "Unref agent unsubscribing from devstate failed"); 02452 } 02453 ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name); 02454 }
static int generic_agent_devstate_unsubscribe | ( | void * | data | ) | [static] |
Definition at line 2432 of file ccss.c.
References ast_event_unsubscribe(), cc_unref(), ast_cc_agent::private_data, and cc_generic_agent_pvt::sub.
Referenced by generic_agent_devstate_cb().
02433 { 02434 struct ast_cc_agent *agent = data; 02435 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02436 02437 if (generic_pvt->sub != NULL) { 02438 generic_pvt->sub = ast_event_unsubscribe(generic_pvt->sub); 02439 } 02440 cc_unref(agent, "Done unsubscribing from devstate"); 02441 return 0; 02442 }
static int generic_monitor_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1053 of file ccss.c.
References CMP_MATCH, CMP_STOP, and generic_monitor_instance_list::device_name.
Referenced by ast_cc_init().
01054 { 01055 const struct generic_monitor_instance_list *generic_list1 = obj; 01056 const struct generic_monitor_instance_list *generic_list2 = arg; 01057 01058 return !strcmp(generic_list1->device_name, generic_list2->device_name) ? CMP_MATCH | CMP_STOP : 0; 01059 }
static void generic_monitor_devstate_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 1159 of file ccss.c.
References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_STATE, ast_free, ast_strdup, ast_taskprocessor_push(), cc_core_taskprocessor, and generic_monitor_devstate_tp_cb().
Referenced by create_new_generic_list().
01160 { 01161 /* Wow, it's cool that we've picked up on a state change, but we really want 01162 * the actual work to be done in the core's taskprocessor execution thread 01163 * so that all monitor operations can be serialized. Locks?! We don't need 01164 * no steenkin' locks! 01165 */ 01166 struct generic_tp_cb_data *gtcd = ast_calloc(1, sizeof(*gtcd)); 01167 01168 if (!gtcd) { 01169 return; 01170 } 01171 01172 if (!(gtcd->device_name = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE)))) { 01173 ast_free(gtcd); 01174 return; 01175 } 01176 gtcd->new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 01177 01178 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_monitor_devstate_tp_cb, gtcd)) { 01179 ast_free((char *)gtcd->device_name); 01180 ast_free(gtcd); 01181 } 01182 }
static int generic_monitor_devstate_tp_cb | ( | void * | data | ) | [static] |
Definition at line 1111 of file ccss.c.
References ast_cc_monitor_callee_available(), AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_free, AST_LIST_TRAVERSE, cc_unref(), generic_monitor_instance::core_id, generic_monitor_instance_list::current_state, generic_tp_cb_data::device_name, find_generic_monitor_instance_list(), generic_monitor_instance_list::fit_for_recall, generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, generic_monitor_instance::monitoring, generic_tp_cb_data::new_state, and cc_monitor_backend::next.
Referenced by generic_monitor_devstate_cb().
01112 { 01113 struct generic_tp_cb_data *gtcd = data; 01114 enum ast_device_state new_state = gtcd->new_state; 01115 enum ast_device_state previous_state = gtcd->new_state; 01116 const char *monitor_name = gtcd->device_name; 01117 struct generic_monitor_instance_list *generic_list; 01118 struct generic_monitor_instance *generic_instance; 01119 01120 if (!(generic_list = find_generic_monitor_instance_list(monitor_name))) { 01121 /* The most likely cause for this is that we destroyed the monitor in the 01122 * time between subscribing to its device state and the time this executes. 01123 * Not really a big deal. 01124 */ 01125 ast_free((char *) gtcd->device_name); 01126 ast_free(gtcd); 01127 return 0; 01128 } 01129 01130 if (generic_list->current_state == new_state) { 01131 /* The device state hasn't actually changed, so we don't really care */ 01132 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback"); 01133 ast_free((char *) gtcd->device_name); 01134 ast_free(gtcd); 01135 return 0; 01136 } 01137 01138 previous_state = generic_list->current_state; 01139 generic_list->current_state = new_state; 01140 01141 if ((new_state == AST_DEVICE_NOT_INUSE || new_state == AST_DEVICE_UNKNOWN) && 01142 (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE || 01143 previous_state == AST_DEVICE_BUSY)) { 01144 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01145 if (!generic_instance->is_suspended && generic_instance->monitoring) { 01146 generic_instance->monitoring = 0; 01147 generic_list->fit_for_recall = 1; 01148 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available"); 01149 break; 01150 } 01151 } 01152 } 01153 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback"); 01154 ast_free((char *) gtcd->device_name); 01155 ast_free(gtcd); 01156 return 0; 01157 }
static int generic_monitor_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1047 of file ccss.c.
References ast_str_hash(), and generic_monitor_instance_list::device_name.
Referenced by ast_cc_init().
01048 { 01049 const struct generic_monitor_instance_list *generic_list = obj; 01050 return ast_str_hash(generic_list->device_name); 01051 }
static void generic_monitor_instance_list_destructor | ( | void * | obj | ) | [static] |
Definition at line 1068 of file ccss.c.
References ast_event_unsubscribe(), ast_free, AST_LIST_REMOVE_HEAD, generic_monitor_instance_list::device_name, generic_monitor_instance_list::list, cc_monitor_backend::next, and generic_monitor_instance_list::sub.
Referenced by create_new_generic_list().
01069 { 01070 struct generic_monitor_instance_list *generic_list = obj; 01071 struct generic_monitor_instance *generic_instance; 01072 01073 generic_list->sub = ast_event_unsubscribe(generic_list->sub); 01074 while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) { 01075 ast_free(generic_instance); 01076 } 01077 ast_free((char *)generic_list->device_name); 01078 }
static void* generic_recall | ( | void * | data | ) | [static] |
Definition at line 2474 of file ccss.c.
References ast_app_run_macro(), ast_cc_agent_recalling(), ast_cc_agent_set_interfaces_chanvar(), ast_cc_failed(), ast_copy_string(), AST_FORMAT_SLINEAR, ast_get_cc_agent_dialstring(), ast_get_cc_callback_macro(), ast_get_cc_recall_timer(), ast_hangup(), ast_log_dynamic_level, ast_pbx_start(), ast_request_and_dial(), ast_setup_cc_recall_datastore(), ast_strdupa, ast_strlen_zero(), ast_cc_agent::cc_params, cc_generic_agent_pvt::cid_name, cc_generic_agent_pvt::cid_num, cc_generic_agent_pvt::context, ast_channel::context, ast_cc_agent::core_id, ast_cc_agent::device_name, cc_generic_agent_pvt::exten, ast_channel::exten, pbx_builtin_setvar_helper(), ast_channel::priority, ast_cc_agent::private_data, and S_OR.
Referenced by cc_generic_agent_recall().
02475 { 02476 struct ast_cc_agent *agent = data; 02477 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02478 const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name)); 02479 const char *tech; 02480 char *target; 02481 int reason; 02482 struct ast_channel *chan; 02483 const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params); 02484 unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000; 02485 02486 tech = interface; 02487 if ((target = strchr(interface, '/'))) { 02488 *target++ = '\0'; 02489 } 02490 if (!(chan = ast_request_and_dial(tech, AST_FORMAT_SLINEAR, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) { 02491 /* Hmm, no channel. Sucks for you, bud. 02492 */ 02493 ast_log_dynamic_level(cc_logger_level, "Core %d: Failed to call back %s for reason %d\n", 02494 agent->core_id, agent->device_name, reason); 02495 ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target); 02496 return NULL; 02497 } 02498 02499 /* We have a channel. It's time now to set up the datastore of recalled CC interfaces. 02500 * This will be a common task for all recall functions. If it were possible, I'd have 02501 * the core do it automatically, but alas I cannot. Instead, I will provide a public 02502 * function to do so. 02503 */ 02504 ast_setup_cc_recall_datastore(chan, agent->core_id); 02505 ast_cc_agent_set_interfaces_chanvar(chan); 02506 02507 ast_copy_string(chan->exten, generic_pvt->exten, sizeof(chan->exten)); 02508 ast_copy_string(chan->context, generic_pvt->context, sizeof(chan->context)); 02509 chan->priority = 1; 02510 02511 pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten); 02512 pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context); 02513 02514 if (!ast_strlen_zero(callback_macro)) { 02515 ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback macro configured for agent %s\n", 02516 agent->core_id, agent->device_name); 02517 if (ast_app_run_macro(NULL, chan, callback_macro, NULL)) { 02518 ast_cc_failed(agent->core_id, "Callback macro to %s failed. Maybe a hangup?", agent->device_name); 02519 ast_hangup(chan); 02520 return NULL; 02521 } 02522 } 02523 ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling", agent->device_name); 02524 ast_pbx_start(chan); 02525 return NULL; 02526 }
static char* handle_cc_kill | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4167 of file ccss.c.
References ao2_t_callback, ast_cli_args::argc, ast_cli_args::argv, ast_cli_complete(), cc_core_instances, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_id(), cc_core_instance::core_id, errno, kill_cores(), ast_cli_args::line, ast_cli_args::n, OBJ_NODATA, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
04168 { 04169 static const char * const option[] = { "core", "all", NULL }; 04170 04171 switch (cmd) { 04172 case CLI_INIT: 04173 e->command = "cc cancel"; 04174 e->usage = 04175 "Usage: cc cancel can be used in two ways.\n" 04176 " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n" 04177 " core ID equal to the specified core ID.\n" 04178 " 2. 'cc cancel all' will cancel all active CC transactions.\n"; 04179 return NULL; 04180 case CLI_GENERATE: 04181 if (a->pos == 2) { 04182 return ast_cli_complete(a->word, option, a->n); 04183 } 04184 if (a->pos == 3) { 04185 return complete_core_id(a->line, a->word, a->pos, a->n); 04186 } 04187 return NULL; 04188 } 04189 04190 if (a->argc == 4) { 04191 int core_id; 04192 char *endptr; 04193 if (strcasecmp(a->argv[2], "core")) { 04194 return CLI_SHOWUSAGE; 04195 } 04196 core_id = strtol(a->argv[3], &endptr, 10); 04197 if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) { 04198 return CLI_SHOWUSAGE; 04199 } 04200 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id"); 04201 } else if (a->argc == 3) { 04202 if (strcasecmp(a->argv[2], "all")) { 04203 return CLI_SHOWUSAGE; 04204 } 04205 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores"); 04206 } else { 04207 return CLI_SHOWUSAGE; 04208 } 04209 04210 return CLI_SUCCESS; 04211 }
static char* handle_cc_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4100 of file ccss.c.
References ast_cli_args::argc, ast_free, ast_malloc, ast_taskprocessor_push(), cc_cli_output_status(), cc_core_taskprocessor, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
04101 { 04102 int *cli_fd; 04103 04104 switch (cmd) { 04105 case CLI_INIT: 04106 e->command = "cc report status"; 04107 e->usage = 04108 "Usage: cc report status\n" 04109 " Report the current status of any ongoing CC transactions\n"; 04110 return NULL; 04111 case CLI_GENERATE: 04112 return NULL; 04113 } 04114 04115 if (a->argc != 3) { 04116 return CLI_SHOWUSAGE; 04117 } 04118 04119 cli_fd = ast_malloc(sizeof(*cli_fd)); 04120 if (!cli_fd) { 04121 return CLI_FAILURE; 04122 } 04123 04124 *cli_fd = a->fd; 04125 04126 if (ast_taskprocessor_push(cc_core_taskprocessor, cc_cli_output_status, cli_fd)) { 04127 ast_free(cli_fd); 04128 return CLI_FAILURE; 04129 } 04130 return CLI_SUCCESS; 04131 }
static int has_device_monitors | ( | struct cc_core_instance * | core_instance | ) | [static] |
check if the core instance has any device monitors
In any case where we end up removing a device monitor from the list of device monitors, it is important to see what the state of the list is afterwards. If we find that we only have extension monitors left, then no devices are actually being monitored. In such a case, we need to declare that CC has failed for this call. This function helps those cases to determine if they should declare failure.
core_instance | The core instance we are checking for the existence of device monitors |
0 | No device monitors exist on this core_instance | |
1 | There is still at least 1 device monitor remaining |
Definition at line 2730 of file ccss.c.
References AST_CC_DEVICE_MONITOR, AST_LIST_TRAVERSE, ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, and cc_monitor_backend::next.
Referenced by cancel_available_timer(), cc_monitor_failed(), request_cc(), suspend(), and unsuspend().
02731 { 02732 struct ast_cc_monitor *iter; 02733 int res = 0; 02734 02735 AST_LIST_TRAVERSE(core_instance->monitors, iter, next) { 02736 if (iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02737 res = 1; 02738 break; 02739 } 02740 } 02741 02742 return res; 02743 }
static void initialize_cc_max_requests | ( | void | ) | [static] |
Definition at line 4019 of file ccss.c.
References ast_config_destroy(), ast_config_load2(), ast_log(), ast_strlen_zero(), ast_variable_retrieve(), config_flags, CONFIG_STATUS_FILEINVALID, GLOBAL_CC_MAX_REQUESTS_DEFAULT, and LOG_WARNING.
Referenced by ast_cc_init().
04020 { 04021 struct ast_config *cc_config; 04022 const char *cc_max_requests_str; 04023 struct ast_flags config_flags = {0,}; 04024 char *endptr; 04025 04026 cc_config = ast_config_load2("ccss.conf", "ccss", config_flags); 04027 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) { 04028 ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests default\n"); 04029 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT; 04030 return; 04031 } 04032 04033 if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) { 04034 ast_config_destroy(cc_config); 04035 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT; 04036 return; 04037 } 04038 04039 global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10); 04040 04041 if (!ast_strlen_zero(endptr)) { 04042 ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n"); 04043 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT; 04044 } 04045 04046 ast_config_destroy(cc_config); 04047 return; 04048 }
static int is_state_change_valid | ( | enum cc_state | current_state, | |
const enum cc_state | new_state, | |||
struct ast_cc_agent * | agent | |||
) | [static] |
Definition at line 2634 of file ccss.c.
References cc_core_instance::agent, AST_CC_AGENT_SKIP_OFFER, ast_log_dynamic_level, ast_test_flag, CC_ACTIVE, CC_AVAILABLE, CC_CALLEE_READY, CC_CALLER_BUSY, CC_CALLER_OFFERED, CC_CALLER_REQUESTED, CC_COMPLETE, CC_FAILED, CC_RECALLING, and ast_cc_agent::core_id.
Referenced by cc_do_state_change().
02635 { 02636 int is_valid = 0; 02637 switch (new_state) { 02638 case CC_AVAILABLE: 02639 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to state %d? That should never happen.\n", 02640 agent->core_id, new_state); 02641 break; 02642 case CC_CALLER_OFFERED: 02643 if (current_state == CC_AVAILABLE) { 02644 is_valid = 1; 02645 } 02646 break; 02647 case CC_CALLER_REQUESTED: 02648 if (current_state == CC_CALLER_OFFERED || 02649 (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) { 02650 is_valid = 1; 02651 } 02652 break; 02653 case CC_ACTIVE: 02654 if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) { 02655 is_valid = 1; 02656 } 02657 break; 02658 case CC_CALLEE_READY: 02659 if (current_state == CC_ACTIVE) { 02660 is_valid = 1; 02661 } 02662 break; 02663 case CC_CALLER_BUSY: 02664 if (current_state == CC_CALLEE_READY) { 02665 is_valid = 1; 02666 } 02667 break; 02668 case CC_RECALLING: 02669 if (current_state == CC_CALLEE_READY) { 02670 is_valid = 1; 02671 } 02672 break; 02673 case CC_COMPLETE: 02674 if (current_state == CC_RECALLING) { 02675 is_valid = 1; 02676 } 02677 break; 02678 case CC_FAILED: 02679 is_valid = 1; 02680 break; 02681 default: 02682 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to unknown state %d\n", 02683 agent->core_id, new_state); 02684 break; 02685 } 02686 02687 return is_valid; 02688 }
static int kill_cores | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4133 of file ccss.c.
References ast_cc_failed(), and cc_core_instance::core_id.
Referenced by handle_cc_kill().
04134 { 04135 int *core_id = arg; 04136 struct cc_core_instance *core_instance = obj; 04137 04138 if (!core_id || (core_instance->core_id == *core_id)) { 04139 ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n"); 04140 } 04141 return 0; 04142 }
static void kill_duplicate_offers | ( | char * | caller | ) | [static] |
Definition at line 2197 of file ccss.c.
References ao2_t_callback_data, cc_core_instances, match_agent(), MATCH_NO_REQUEST, OBJ_NODATA, and OBJ_UNLINK.
Referenced by cc_core_init_instance().
02198 { 02199 unsigned long match_flags = MATCH_NO_REQUEST; 02200 ao2_t_callback_data(cc_core_instances, OBJ_UNLINK | OBJ_NODATA, match_agent, caller, &match_flags, "Killing duplicate offers"); 02201 }
static int match_agent | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 449 of file ccss.c.
References cc_core_instance::agent, CC_CALLER_REQUESTED, CMP_MATCH, CMP_STOP, cc_core_instance::current_state, ast_cc_agent::device_name, MATCH_NO_REQUEST, MATCH_REQUEST, and name.
Referenced by cccancel_exec(), ccreq_exec(), and kill_duplicate_offers().
00450 { 00451 struct cc_core_instance *core_instance = obj; 00452 const char *name = arg; 00453 unsigned long match_flags = *(unsigned long *)data; 00454 int possible_match = 0; 00455 00456 if ((match_flags & MATCH_NO_REQUEST) && core_instance->current_state < CC_CALLER_REQUESTED) { 00457 possible_match = 1; 00458 } 00459 00460 if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) { 00461 possible_match = 1; 00462 } 00463 00464 if (!possible_match) { 00465 return 0; 00466 } 00467 00468 if (!strcmp(core_instance->agent->device_name, name)) { 00469 return CMP_MATCH | CMP_STOP; 00470 } 00471 return 0; 00472 }
static const char* monitor_policy_to_str | ( | enum ast_cc_monitor_policies | policy | ) | [static] |
Definition at line 596 of file ccss.c.
References AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, and AST_CC_MONITOR_NEVER.
Referenced by ast_cc_get_param().
00597 { 00598 switch (policy) { 00599 case AST_CC_MONITOR_NEVER: 00600 return "never"; 00601 case AST_CC_MONITOR_NATIVE: 00602 return "native"; 00603 case AST_CC_MONITOR_GENERIC: 00604 return "generic"; 00605 case AST_CC_MONITOR_ALWAYS: 00606 return "always"; 00607 default: 00608 /* This should never happen... */ 00609 return ""; 00610 } 00611 }
static int offer_timer_expire | ( | const void * | data | ) | [static] |
Definition at line 2362 of file ccss.c.
References ast_cc_failed(), ast_log_dynamic_level, cc_unref(), ast_cc_agent::core_id, ast_cc_agent::device_name, cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.
Referenced by cc_generic_agent_start_offer_timer().
02363 { 02364 struct ast_cc_agent *agent = (struct ast_cc_agent *) data; 02365 struct cc_generic_agent_pvt *agent_pvt = agent->private_data; 02366 ast_log_dynamic_level(cc_logger_level, "Core %d: Queuing change request because offer timer has expired.\n", 02367 agent->core_id); 02368 agent_pvt->offer_timer_id = -1; 02369 ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name); 02370 cc_unref(agent, "Remove scheduler's reference to the agent"); 02371 return 0; 02372 }
static int print_stats_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4070 of file ccss.c.
References cc_core_instance::agent, ast_cli(), AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, cc_cli_print_monitor_stats(), cc_state_to_string(), cc_core_instance::core_id, cc_core_instance::current_state, ast_cc_agent::device_name, and cc_core_instance::monitors.
Referenced by cc_cli_output_status().
04071 { 04072 int *cli_fd = arg; 04073 struct cc_core_instance *core_instance = obj; 04074 04075 ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name, 04076 cc_state_to_string(core_instance->current_state)); 04077 AST_LIST_LOCK(core_instance->monitors); 04078 cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0); 04079 AST_LIST_UNLOCK(core_instance->monitors); 04080 return 0; 04081 }
static void request_cc | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2745 of file ccss.c.
References cc_core_instance::agent, AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, has_device_monitors(), ast_cc_monitor::interface, manager_event, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor_callbacks::request_cc.
Referenced by cc_caller_requested().
02746 { 02747 struct ast_cc_monitor *monitor_iter; 02748 AST_LIST_LOCK(core_instance->monitors); 02749 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02750 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02751 if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) { 02752 AST_LIST_REMOVE_CURRENT(next); 02753 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02754 monitor_iter->interface->device_name, 1); 02755 cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor"); 02756 } else { 02757 manager_event(EVENT_FLAG_CC, "CCRequested", 02758 "CoreID: %d\r\n" 02759 "Caller: %s\r\n" 02760 "Callee: %s\r\n", 02761 core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name); 02762 } 02763 } 02764 } 02765 AST_LIST_TRAVERSE_SAFE_END; 02766 02767 if (!has_device_monitors(core_instance)) { 02768 ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC"); 02769 } 02770 AST_LIST_UNLOCK(core_instance->monitors); 02771 }
static enum ast_cc_agent_policies str_to_agent_policy | ( | const char *const | value | ) | [static] |
Definition at line 551 of file ccss.c.
References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, AST_CC_AGENT_NEVER, ast_log(), and LOG_WARNING.
Referenced by ast_cc_set_param().
00552 { 00553 if (!strcasecmp(value, "never")) { 00554 return AST_CC_AGENT_NEVER; 00555 } else if (!strcasecmp(value, "native")) { 00556 return AST_CC_AGENT_NATIVE; 00557 } else if (!strcasecmp(value, "generic")) { 00558 return AST_CC_AGENT_GENERIC; 00559 } else { 00560 ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value); 00561 return AST_CC_AGENT_NEVER; 00562 } 00563 }
static enum ast_cc_monitor_policies str_to_monitor_policy | ( | const char *const | value | ) | [static] |
Definition at line 565 of file ccss.c.
References AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, ast_log(), and LOG_WARNING.
Referenced by ast_cc_set_param().
00566 { 00567 if (!strcasecmp(value, "never")) { 00568 return AST_CC_MONITOR_NEVER; 00569 } else if (!strcasecmp(value, "native")) { 00570 return AST_CC_MONITOR_NATIVE; 00571 } else if (!strcasecmp(value, "generic")) { 00572 return AST_CC_MONITOR_GENERIC; 00573 } else if (!strcasecmp(value, "always")) { 00574 return AST_CC_MONITOR_ALWAYS; 00575 } else { 00576 ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value); 00577 return AST_CC_MONITOR_NEVER; 00578 } 00579 }
static void suspend | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2840 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor_callbacks::suspend.
Referenced by build_suspend(), cc_caller_busy(), and handle_controlstreamfile().
02841 { 02842 struct ast_cc_monitor *monitor_iter; 02843 AST_LIST_LOCK(core_instance->monitors); 02844 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02845 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02846 if (monitor_iter->callbacks->suspend(monitor_iter)) { 02847 AST_LIST_REMOVE_CURRENT(next); 02848 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02849 monitor_iter->interface->device_name, 1); 02850 cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor"); 02851 } 02852 } 02853 } 02854 AST_LIST_TRAVERSE_SAFE_END; 02855 02856 if (!has_device_monitors(core_instance)) { 02857 ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC"); 02858 } 02859 AST_LIST_UNLOCK(core_instance->monitors); 02860 }
static void unsuspend | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2787 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor_callbacks::unsuspend.
Referenced by cc_active().
02788 { 02789 struct ast_cc_monitor *monitor_iter; 02790 AST_LIST_LOCK(core_instance->monitors); 02791 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02792 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02793 if (monitor_iter->callbacks->unsuspend(monitor_iter)) { 02794 AST_LIST_REMOVE_CURRENT(next); 02795 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02796 monitor_iter->interface->device_name, 1); 02797 cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor"); 02798 } 02799 } 02800 } 02801 AST_LIST_TRAVERSE_SAFE_END; 02802 02803 if (!has_device_monitors(core_instance)) { 02804 ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC"); 02805 } 02806 AST_LIST_UNLOCK(core_instance->monitors); 02807 }
struct ast_cli_entry cc_cli[] [static] |
Initial value:
{ { .handler = handle_cc_status , .summary = "Reports CC stats" ,__VA_ARGS__ }, { .handler = handle_cc_kill , .summary = "Kill a CC transaction" ,__VA_ARGS__ }, }
Definition at line 4213 of file ccss.c.
Referenced by ast_cc_init().
struct ao2_container* cc_core_instances [static] |
Definition at line 284 of file ccss.c.
Referenced by ast_cc_agent_callback(), ast_cc_init(), ast_cc_monitor_count(), cc_cli_output_status(), cc_complete(), cc_core_init_instance(), cc_failed(), cccancel_exec(), ccreq_exec(), complete_core_id(), count_agents(), find_cc_core_instance(), handle_cc_kill(), and kill_duplicate_offers().
const int CC_CORE_INSTANCES_BUCKETS = 17 [static] |
struct ast_taskprocessor* cc_core_taskprocessor [static] |
Taskprocessor from which all CC agent and monitor callbacks are called.
Definition at line 83 of file ccss.c.
Referenced by ast_cc_agent_status_response(), ast_cc_init(), ast_cc_monitor_failed(), ast_cc_monitor_party_b_free(), ast_cc_monitor_status_request(), ast_cc_monitor_stop_ringing(), cc_request_state_change(), generic_agent_devstate_cb(), generic_monitor_devstate_cb(), and handle_cc_status().
struct ast_cc_config_params cc_default_params [static] |
int cc_logger_level [static] |
const char* CC_LOGGER_LEVEL_NAME = "CC" [static] |
int cc_request_count [static] |
struct ast_sched_thread* cc_sched_thread [static] |
The sched_thread ID used for all generic CC timeouts
Definition at line 73 of file ccss.c.
Referenced by ast_cc_init(), cc_generic_agent_start_offer_timer(), cc_generic_agent_stop_offer_timer(), cc_generic_monitor_cancel_available_timer(), and cc_generic_monitor_request_cc().
struct { ... } cc_service_to_string_map[] [static] |
Referenced by cc_service_to_string().
struct { ... } cc_state_to_string_map[] [static] |
Referenced by cc_state_to_string().
const char* cccancel_app = "CallCompletionCancel" [static] |
int core_id_counter [static] |
int dialed_cc_interface_counter [static] |
struct ast_datastore_info dialed_cc_interfaces_info [static] |
Initial value:
{ .type = "Dial CC Interfaces", .duplicate = dialed_cc_interfaces_duplicate, .destroy = dialed_cc_interfaces_destroy, }
Definition at line 1664 of file ccss.c.
Referenced by ast_cc_call_init(), ast_cc_extension_monitor_add_dialstring(), ast_cc_get_current_core_id(), ast_cc_offer(), ast_handle_cc_control_frame(), ast_ignore_cc(), cc_build_payload(), and cc_interfaces_datastore_init().
struct ast_cc_agent_callbacks generic_agent_callbacks [static] |
struct ast_cc_monitor_callbacks generic_monitor_cbs [static] |
struct ao2_container* generic_monitors |
Definition at line 997 of file ccss.c.
Referenced by ast_cc_init(), cc_generic_monitor_destructor(), create_new_generic_list(), and find_generic_monitor_instance_list().
unsigned int global_cc_max_requests [static] |
struct ast_datastore_info recall_ds_info [static] |
Initial value:
{ .type = "cc_recall", .duplicate = cc_recall_ds_duplicate, .destroy = cc_recall_ds_destroy, }
Definition at line 3054 of file ccss.c.
Referenced by ast_cc_agent_set_interfaces_chanvar(), ast_cc_completed(), ast_cc_is_recall(), ast_ignore_cc(), ast_set_cc_interfaces_chanvar(), and ast_setup_cc_recall_datastore().
const char* service_string |
int(* const[]) state_change_funcs(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state) [static] |
const char* state_string |