Call Completion Supplementary Services implementation. More...
#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 | |
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. | |
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. | |
struct 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. | |
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. | |
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_is_device_available (enum ast_device_state state) |
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 void | cc_shutdown (void) |
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 |
struct 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) |
Call Completion Supplementary Services implementation.
Definition in file ccss.c.
#define GLOBAL_CC_MAX_REQUESTS_DEFAULT 20 |
Definition at line 543 of file ccss.c.
Referenced by initialize_cc_max_requests().
enum cc_state |
The states used in the CCSS core state machine.
CC_AVAILABLE |
Entered when it is determined that CCSS may be used for the call |
CC_CALLER_OFFERED |
Entered when a CCSS agent has offered CCSS to a caller |
CC_CALLER_REQUESTED |
Entered when a CCSS agent confirms that a caller has requested CCSS |
CC_ACTIVE |
Entered when a CCSS monitor confirms acknowledgment of an outbound CCSS request |
CC_CALLEE_READY |
Entered when a CCSS monitor alerts the core that the called party has become available |
CC_CALLER_BUSY |
Entered when a CCSS agent alerts the core that the calling party may not be recalled because he is unavailable |
CC_RECALLING |
Entered when a CCSS agent alerts the core that the calling party is attempting to recall the called party |
CC_COMPLETE |
Entered when an application alerts the core that the calling party's recall attempt has had a call progress response indicated |
CC_FAILED |
Entered any time that something goes wrong during the process, thus resulting in the failure of the attempted CCSS transaction. Note also that cancellations of CC are treated as failures. |
Definition at line 171 of file ccss.c.
00171 { 00172 /*! Entered when it is determined that CCSS may be used for the call */ 00173 CC_AVAILABLE, 00174 /*! Entered when a CCSS agent has offered CCSS to a caller */ 00175 CC_CALLER_OFFERED, 00176 /*! Entered when a CCSS agent confirms that a caller has 00177 * requested CCSS */ 00178 CC_CALLER_REQUESTED, 00179 /*! Entered when a CCSS monitor confirms acknowledgment of an 00180 * outbound CCSS request */ 00181 CC_ACTIVE, 00182 /*! Entered when a CCSS monitor alerts the core that the called party 00183 * has become available */ 00184 CC_CALLEE_READY, 00185 /*! Entered when a CCSS agent alerts the core that the calling party 00186 * may not be recalled because he is unavailable 00187 */ 00188 CC_CALLER_BUSY, 00189 /*! Entered when a CCSS agent alerts the core that the calling party 00190 * is attempting to recall the called party 00191 */ 00192 CC_RECALLING, 00193 /*! Entered when an application alerts the core that the calling party's 00194 * recall attempt has had a call progress response indicated 00195 */ 00196 CC_COMPLETE, 00197 /*! Entered any time that something goes wrong during the process, thus 00198 * resulting in the failure of the attempted CCSS transaction. Note also 00199 * that cancellations of CC are treated as failures. 00200 */ 00201 CC_FAILED, 00202 };
enum match_flags |
Definition at line 459 of file ccss.c.
00459 { 00460 /* Only match agents that have not yet 00461 * made a CC request 00462 */ 00463 MATCH_NO_REQUEST = (1 << 0), 00464 /* Only match agents that have made 00465 * a CC request 00466 */ 00467 MATCH_REQUEST = (1 << 1), 00468 };
struct ast_cc_config_params* __ast_cc_config_params_init | ( | const char * | file, | |
int | line, | |||
const char * | function | |||
) | [read] |
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 563 of file ccss.c.
References __ast_malloc(), ast_cc_default_config_params(), and ast_malloc.
00564 { 00565 #if defined(__AST_DEBUG_MALLOC) 00566 struct ast_cc_config_params *params = __ast_malloc(sizeof(*params), file, line, function); 00567 #else 00568 struct ast_cc_config_params *params = ast_malloc(sizeof(*params)); 00569 #endif 00570 00571 if (!params) { 00572 return NULL; 00573 } 00574 00575 ast_cc_default_config_params(params); 00576 return params; 00577 }
static void agent_destroy | ( | void * | data | ) | [static] |
Definition at line 2281 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().
02282 { 02283 struct ast_cc_agent *agent = data; 02284 02285 if (agent->callbacks) { 02286 agent->callbacks->destructor(agent); 02287 } 02288 ast_cc_config_params_destroy(agent->cc_params); 02289 }
static const char* agent_policy_to_str | ( | enum ast_cc_agent_policies | policy | ) | [static] |
Definition at line 614 of file ccss.c.
References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, and AST_CC_AGENT_NEVER.
Referenced by ast_cc_get_param().
00615 { 00616 switch (policy) { 00617 case AST_CC_AGENT_NEVER: 00618 return "never"; 00619 case AST_CC_AGENT_NATIVE: 00620 return "native"; 00621 case AST_CC_AGENT_GENERIC: 00622 return "generic"; 00623 default: 00624 /* This should never happen... */ 00625 return ""; 00626 } 00627 }
int ast_cc_agent_accept_request | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Accept inbound CC request.
When a caller requests CC, this function should be called to let the core know that the request has been accepted.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3510 of file ccss.c.
References CC_CALLER_REQUESTED, and cc_request_state_change().
Referenced by ccreq_exec(), and handle_cc_subscribe().
03511 { 03512 va_list ap; 03513 int res; 03514 03515 va_start(ap, debug); 03516 res = cc_request_state_change(CC_CALLER_REQUESTED, core_id, debug, ap); 03517 va_end(ap); 03518 return res; 03519 }
struct ast_cc_agent* ast_cc_agent_callback | ( | int | flags, | |
ao2_callback_fn * | function, | |||
void * | arg, | |||
const char *const | type | |||
) | [read] |
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 446 of file ccss.c.
References cc_core_instance::agent, ao2_t_callback, cc_agent_callback_helper(), 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().
00447 { 00448 struct cc_callback_helper helper = {.function = function, .args = args, .type = type}; 00449 struct cc_core_instance *core_instance; 00450 if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper, 00451 "Calling provided agent callback function"))) { 00452 struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent"); 00453 cc_unref(core_instance, "agent callback done with the core_instance"); 00454 return agent; 00455 } 00456 return NULL; 00457 }
int ast_cc_agent_caller_available | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate that a previously unavailable caller has become available.
If a monitor is suspended due to a caller becoming unavailable, then this function should be called to indicate that the 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 3554 of file ccss.c.
References CC_ACTIVE, and cc_request_state_change().
Referenced by generic_agent_devstate_cb().
03555 { 03556 va_list ap; 03557 int res; 03558 03559 va_start(ap, debug); 03560 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap); 03561 va_end(ap); 03562 return res; 03563 }
int ast_cc_agent_caller_busy | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate that the caller is busy.
When the callee makes it known that he is available, the core will let the caller's channel driver know that it may attempt to let the caller know to attempt a recall. If the channel driver can detect, though, that the caller is busy, then the channel driver should call this function to let the CC core know.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3543 of file ccss.c.
References CC_CALLER_BUSY, and cc_request_state_change().
Referenced by cc_generic_agent_recall(), and sip_cc_agent_recall().
03544 { 03545 va_list ap; 03546 int res; 03547 03548 va_start(ap, debug); 03549 res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap); 03550 va_end(ap); 03551 return res; 03552 }
int ast_cc_agent_recalling | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Tell the CC core that a caller is currently recalling.
The main purpose of this is so that the core can alert the monitor to stop its available timer since the caller has begun its recall phase.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3565 of file ccss.c.
References CC_RECALLING, and cc_request_state_change().
Referenced by generic_recall(), and get_destination().
03566 { 03567 va_list ap; 03568 int res; 03569 03570 va_start(ap, debug); 03571 res = cc_request_state_change(CC_RECALLING, core_id, debug, ap); 03572 va_end(ap); 03573 return res; 03574 }
int ast_cc_agent_register | ( | const struct ast_cc_agent_callbacks * | callbacks | ) |
Register a set of agent callbacks with the core.
This is made so that at agent creation time, the proper callbacks may be installed and the proper .init callback may be called for the monitor to establish private data.
callbacks | The callbacks used by the agent implementation |
0 | Successfully registered | |
-1 | Failure to register |
Definition at line 950 of file ccss.c.
References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and cc_agent_backend::callbacks.
Referenced by ast_cc_init(), and load_module().
00951 { 00952 struct cc_agent_backend *backend = ast_calloc(1, sizeof(*backend)); 00953 00954 if (!backend) { 00955 return -1; 00956 } 00957 00958 backend->callbacks = callbacks; 00959 AST_RWLIST_WRLOCK(&cc_agent_backends); 00960 AST_RWLIST_INSERT_TAIL(&cc_agent_backends, backend, next); 00961 AST_RWLIST_UNLOCK(&cc_agent_backends); 00962 return 0; 00963 }
int ast_cc_agent_set_interfaces_chanvar | ( | struct ast_channel * | chan | ) |
Set the first level CC_INTERFACES channel variable for a channel.
The CC_INTERFACES channel variable will have the interfaces that should be called back for a specific PBX instance.
chan | The channel to set the CC_INTERFACES variable on |
Definition at line 3365 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(), and str.
Referenced by generic_recall(), and handle_request_invite().
03366 { 03367 struct ast_datastore *recall_datastore; 03368 struct cc_monitor_tree *interface_tree; 03369 struct ast_cc_monitor *monitor; 03370 struct cc_recall_ds_data *recall_data; 03371 struct ast_str *str = ast_str_create(64); 03372 int core_id; 03373 03374 if (!str) { 03375 return -1; 03376 } 03377 03378 ast_channel_lock(chan); 03379 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03380 ast_channel_unlock(chan); 03381 ast_free(str); 03382 return -1; 03383 } 03384 recall_data = recall_datastore->data; 03385 interface_tree = recall_data->interface_tree; 03386 core_id = recall_data->core_id; 03387 ast_channel_unlock(chan); 03388 03389 AST_LIST_LOCK(interface_tree); 03390 monitor = AST_LIST_FIRST(interface_tree); 03391 build_cc_interfaces_chanvar(monitor, &str); 03392 AST_LIST_UNLOCK(interface_tree); 03393 03394 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str)); 03395 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n", 03396 core_id, ast_str_buffer(str)); 03397 03398 ast_free(str); 03399 return 0; 03400 }
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 3830 of file ccss.c.
References args, ast_calloc, ast_free, ast_taskprocessor_push(), cc_status_response(), cc_unref(), cc_status_response_args::core_instance, cc_status_response_args::devstate, and find_cc_core_instance().
Referenced by cc_generic_agent_status_request(), and sip_cc_agent_status_request().
03831 { 03832 struct cc_status_response_args *args; 03833 struct cc_core_instance *core_instance; 03834 int res; 03835 03836 args = ast_calloc(1, sizeof(*args)); 03837 if (!args) { 03838 return -1; 03839 } 03840 03841 core_instance = find_cc_core_instance(core_id); 03842 if (!core_instance) { 03843 ast_free(args); 03844 return -1; 03845 } 03846 03847 args->core_instance = core_instance; 03848 args->devstate = devstate; 03849 03850 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_response, args); 03851 if (res) { 03852 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03853 ast_free(args); 03854 } 03855 return res; 03856 }
void ast_cc_agent_unregister | ( | const struct ast_cc_agent_callbacks * | callbacks | ) |
Unregister a set of agent callbacks with the core.
If a module which makes use of a CC agent is unloaded, then it may unregister its agent callbacks with the core.
callbacks | The callbacks used by the agent implementation |
0 | Successfully unregistered | |
-1 | Failure to unregister |
Definition at line 965 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_agent_backend::callbacks, and cc_monitor_backend::next.
Referenced by __unload_module(), cc_shutdown(), and unload_module().
00966 { 00967 struct cc_agent_backend *backend; 00968 AST_RWLIST_WRLOCK(&cc_agent_backends); 00969 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_agent_backends, backend, next) { 00970 if (backend->callbacks == callbacks) { 00971 AST_RWLIST_REMOVE_CURRENT(next); 00972 ast_free(backend); 00973 break; 00974 } 00975 } 00976 AST_RWLIST_TRAVERSE_SAFE_END; 00977 AST_RWLIST_UNLOCK(&cc_agent_backends); 00978 }
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 1239 of file ccss.c.
References ast_cc_monitor_failed(), ast_cc_monitor::available_timer_id, cc_unref(), ast_cc_monitor::core_id, ast_cc_interface::device_name, ast_cc_monitor::interface, and monitor.
Referenced by cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().
01240 { 01241 struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data; 01242 int res; 01243 monitor->available_timer_id = -1; 01244 res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor"); 01245 cc_unref(monitor, "Unref reference from scheduler\n"); 01246 return res; 01247 }
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_dahdi is weird. It doesn't seem to actually queue frames when it needs to tell an application something. Instead it wakes up, tells the application that it has data ready, and then based on set flags, creates the proper frame type. For chan_dahdi, we provide this function. It provides us the data we need, and we'll make its frame for it.
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 3913 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().
03917 { 03918 struct cc_control_payload *payload = ast_calloc(1, sizeof(*payload)); 03919 03920 if (!payload) { 03921 return -1; 03922 } 03923 if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) { 03924 /* Something screwed up, we can't make a frame with this */ 03925 ast_free(payload); 03926 return -1; 03927 } 03928 frame->frametype = AST_FRAME_CONTROL; 03929 frame->subclass.integer = AST_CONTROL_CC; 03930 frame->data.ptr = payload; 03931 frame->datalen = sizeof(*payload); 03932 frame->mallocd = AST_MALLOCD_DATA; 03933 return 0; 03934 }
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. |
For channel types that fail ast_request when the device is busy, we call into the channel driver with ast_cc_callback. This is the callback that is called in that case for each device found which could have been returned by ast_request.
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 3969 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().
03971 { 03972 struct cc_control_payload payload; 03973 if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) { 03974 /* Something screwed up. Don't try to handle this payload */ 03975 call_destructor_with_no_monitor(monitor_type, private_data); 03976 return; 03977 } 03978 ast_handle_cc_control_frame(inbound, NULL, &payload); 03979 }
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 3936 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().
03937 { 03938 char device_name[AST_CHANNEL_NAME]; 03939 struct cc_control_payload payload; 03940 struct ast_cc_config_params *cc_params; 03941 03942 if (outgoing->hangupcause != AST_CAUSE_BUSY && outgoing->hangupcause != AST_CAUSE_CONGESTION) { 03943 /* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call 03944 * failing is something other than busy or congestion 03945 */ 03946 return; 03947 } 03948 03949 cc_params = ast_channel_get_cc_config_params(outgoing); 03950 if (!cc_params) { 03951 return; 03952 } 03953 if (ast_get_cc_monitor_policy(cc_params) != AST_CC_MONITOR_GENERIC) { 03954 /* This sort of CCBS only works if using generic CC. For native, we would end up sending 03955 * a CC request for a non-existent call. The far end will reject this every time 03956 */ 03957 return; 03958 } 03959 03960 ast_channel_get_device_name(outgoing, device_name, sizeof(device_name)); 03961 if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name, 03962 dialstring, AST_CC_CCBS, NULL, &payload)) { 03963 /* Something screwed up, we can't make a frame with this */ 03964 return; 03965 } 03966 ast_handle_cc_control_frame(incoming, outgoing, &payload); 03967 }
int ast_cc_call_init | ( | struct ast_channel * | chan, | |
int * | ignore_cc | |||
) |
Start the CC process on a call.
Whenever a CC-capable application, such as Dial, wishes to engage in CC activity, it initiates the process by calling this function. If the CC core should discover that a previous application has called ast_ignore_cc on this channel or a "parent" channel, then the value of the ignore_cc integer passed in will be set nonzero.
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 2146 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_cc_monitor::core_id, ast_datastore::data, dialed_cc_interfaces::dial_parent_id, ast_channel::exten, ast_cc_monitor::id, dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, ast_channel::macrocontext, ast_channel::macroexten, monitor, and S_OR.
Referenced by dial_exec_full().
02147 { 02148 /* There are three situations to deal with here: 02149 * 02150 * 1. The channel does not have a dialed_cc_interfaces datastore on 02151 * it. This means that this is the first time that Dial has 02152 * been called. We need to create/initialize the datastore. 02153 * 02154 * 2. The channel does have a cc_interface datastore on it and 02155 * the "ignore" indicator is 0. This means that a Local channel 02156 * was called by a "parent" dial. We can check the datastore's 02157 * parent field to see who the root of this particular dial tree 02158 * is. 02159 * 02160 * 3. The channel does have a cc_interface datastore on it and 02161 * the "ignore" indicator is 1. This means that a second Dial call 02162 * is being made from an extension. In this case, we do not 02163 * want to make any additions/modifications to the datastore. We 02164 * will instead set a flag to indicate that CCSS is completely 02165 * disabled for this Dial attempt. 02166 */ 02167 02168 struct ast_datastore *cc_interfaces_datastore; 02169 struct dialed_cc_interfaces *interfaces; 02170 struct ast_cc_monitor *monitor; 02171 struct ast_cc_config_params *cc_params; 02172 02173 ast_channel_lock(chan); 02174 02175 cc_params = ast_channel_get_cc_config_params(chan); 02176 if (!cc_params) { 02177 ast_channel_unlock(chan); 02178 return -1; 02179 } 02180 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) { 02181 /* We can't offer CC to this caller anyway, so don't bother with CC on this call 02182 */ 02183 *ignore_cc = 1; 02184 ast_channel_unlock(chan); 02185 ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", chan->name); 02186 return 0; 02187 } 02188 02189 if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) { 02190 /* Situation 1 has occurred */ 02191 ast_channel_unlock(chan); 02192 return cc_interfaces_datastore_init(chan); 02193 } 02194 interfaces = cc_interfaces_datastore->data; 02195 ast_channel_unlock(chan); 02196 02197 if (interfaces->ignore) { 02198 /* Situation 3 has occurred */ 02199 *ignore_cc = 1; 02200 ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n"); 02201 return 0; 02202 } 02203 02204 /* Situation 2 has occurred */ 02205 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten), 02206 S_OR(chan->macrocontext, chan->context), interfaces->dial_parent_id))) { 02207 return -1; 02208 } 02209 monitor->core_id = interfaces->core_id; 02210 AST_LIST_LOCK(interfaces->interface_tree); 02211 cc_ref(monitor, "monitor tree's reference to the monitor"); 02212 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next); 02213 AST_LIST_UNLOCK(interfaces->interface_tree); 02214 interfaces->dial_parent_id = monitor->id; 02215 cc_unref(monitor, "Unref monitor's allocation reference"); 02216 return 0; 02217 }
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 3981 of file ccss.c.
References ast_get_channel_tech(), and ast_channel_tech::cc_callback.
Referenced by dial_exec_full().
03982 { 03983 const struct ast_channel_tech *chantech = ast_get_channel_tech(tech); 03984 03985 if (chantech && chantech->cc_callback) { 03986 chantech->cc_callback(inbound, dest, callback); 03987 } 03988 03989 return 0; 03990 }
int ast_cc_completed | ( | struct ast_channel * | chan, | |
const char *const | debug, | |||
... | ||||
) |
Indicate recall has been acknowledged.
When we receive confirmation that an endpoint has responded to our CC recall, we call this function.
chan | The inbound channel making the CC recall | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3576 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, and cc_recall_ds_data::nested.
Referenced by wait_for_answer().
03577 { 03578 struct ast_datastore *recall_datastore; 03579 struct cc_recall_ds_data *recall_data; 03580 int core_id; 03581 va_list ap; 03582 int res; 03583 03584 ast_channel_lock(chan); 03585 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03586 /* Silly! Why did you call this function if there's no recall DS? */ 03587 ast_channel_unlock(chan); 03588 return -1; 03589 } 03590 recall_data = recall_datastore->data; 03591 if (recall_data->nested || recall_data->ignore) { 03592 /* If this is being called from a nested Dial, it is too 03593 * early to determine if the recall has actually completed. 03594 * The outermost dial is the only one with the authority to 03595 * declare the recall to be complete. 03596 * 03597 * Similarly, if this function has been called when the 03598 * recall has progressed beyond the first dial, this is not 03599 * a legitimate time to declare the recall to be done. In fact, 03600 * that should have been done already. 03601 */ 03602 ast_channel_unlock(chan); 03603 return -1; 03604 } 03605 core_id = recall_data->core_id; 03606 ast_channel_unlock(chan); 03607 va_start(ap, debug); 03608 res = cc_request_state_change(CC_COMPLETE, core_id, debug, ap); 03609 va_end(ap); 03610 return res; 03611 }
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 579 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(), process_dahdi(), setup_dahdi(), and sip_destroy_peer().
00580 { 00581 ast_free(params); 00582 }
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
For now, this is a simple memcpy, but this function is necessary since the size of an ast_cc_config_params structure is unknown outside of main/ccss.c. Also, this allows for easier expansion of the function in case it becomes more complex than just a memcpy.
src | The structure from which data is copied | |
dest | The structure to which data is copied |
Definition at line 741 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(), duplicate_pseudo(), and mkintf().
void ast_cc_default_config_params | ( | struct ast_cc_config_params * | params | ) |
Set the specified CC config params to default values.
This is just like ast_cc_copy_config_params() and could be used in place of it if you need to set the config params to defaults instead. You are simply "copying" defaults into the destination.
params | CC config params to set to default values. |
Definition at line 558 of file ccss.c.
Referenced by __ast_cc_config_params_init().
00559 { 00560 *params = cc_default_params; 00561 }
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.
Whenever we request a channel, the parent extension monitor needs to store the dialstring of the device requested. The reason is so that we can call the device back during the recall even if we are not monitoring the device.
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 1735 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, extension_child_dialstring::device_name, dialed_cc_interfaces::dial_parent_id, ast_cc_monitor::id, id, dialed_cc_interfaces::interface_tree, extension_child_dialstring::is_valid, monitor, extension_child_dialstring::original_dialstring, and ast_cc_monitor::private_data.
Referenced by dial_exec_full().
01736 { 01737 struct ast_datastore *cc_datastore; 01738 struct dialed_cc_interfaces *cc_interfaces; 01739 struct ast_cc_monitor *monitor; 01740 struct extension_monitor_pvt *extension_pvt; 01741 struct extension_child_dialstring *child_dialstring; 01742 struct cc_monitor_tree *interface_tree; 01743 int id; 01744 01745 ast_channel_lock(incoming); 01746 if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) { 01747 ast_channel_unlock(incoming); 01748 return; 01749 } 01750 01751 cc_interfaces = cc_datastore->data; 01752 interface_tree = cc_interfaces->interface_tree; 01753 id = cc_interfaces->dial_parent_id; 01754 ast_channel_unlock(incoming); 01755 01756 AST_LIST_LOCK(interface_tree); 01757 AST_LIST_TRAVERSE(interface_tree, monitor, next) { 01758 if (monitor->id == id) { 01759 break; 01760 } 01761 } 01762 01763 if (!monitor) { 01764 AST_LIST_UNLOCK(interface_tree); 01765 return; 01766 } 01767 01768 extension_pvt = monitor->private_data; 01769 if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) { 01770 AST_LIST_UNLOCK(interface_tree); 01771 return; 01772 } 01773 ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring)); 01774 ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name)); 01775 child_dialstring->is_valid = 1; 01776 AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next); 01777 AST_LIST_UNLOCK(interface_tree); 01778 }
int ast_cc_failed | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate failure has occurred.
If at any point a failure occurs, this is the function to call so that the core can initiate cleanup procedures.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3613 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(), sip_offer_timer_expire(), suspend(), unsuspend(), and wait_for_answer().
03614 { 03615 va_list ap; 03616 int res; 03617 03618 va_start(ap, debug); 03619 res = cc_request_state_change(CC_FAILED, core_id, debug, ap); 03620 va_end(ap); 03621 return res; 03622 }
int ast_cc_get_current_core_id | ( | struct ast_channel * | chan | ) |
Get the core id for the current call.
The main use of this function is for channel drivers who queue an AST_CONTROL_CC frame. A channel driver may call this function in order to get the core_id for what may become a CC request. This way, when monitor functions are called which use a core_id as a means of identification, the channel driver will have saved this information.
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 2224 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, dialed_cc_interfaces::core_id, ast_datastore::data, and dialed_cc_interfaces::ignore.
Referenced by sip_handle_cc().
02225 { 02226 struct ast_datastore *datastore; 02227 struct dialed_cc_interfaces *cc_interfaces; 02228 int core_id_return; 02229 02230 ast_channel_lock(chan); 02231 if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) { 02232 ast_channel_unlock(chan); 02233 return -1; 02234 } 02235 02236 cc_interfaces = datastore->data; 02237 core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id; 02238 ast_channel_unlock(chan); 02239 return core_id_return; 02240 02241 }
struct ast_cc_monitor* ast_cc_get_monitor_by_recall_core_id | ( | const int | core_id, | |
const char *const | device_name | |||
) | [read] |
Get the associated monitor given the device name and core_id.
The function ast_cc_is_recall is helpful for determining if a call to a specific channel is a recall. However, once you have determined that this is a recall, you will most likely need access to the private data within the associated monitor. This function is what one uses to get that monitor.
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 3253 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, and cc_core_instance::monitors.
Referenced by sip_call().
03254 { 03255 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03256 struct ast_cc_monitor *monitor_iter; 03257 03258 if (!core_instance) { 03259 return NULL; 03260 } 03261 03262 AST_LIST_LOCK(core_instance->monitors); 03263 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 03264 if (!strcmp(monitor_iter->interface->device_name, device_name)) { 03265 /* Found a monitor. */ 03266 cc_ref(monitor_iter, "Hand the requester of the monitor a reference"); 03267 break; 03268 } 03269 } 03270 AST_LIST_UNLOCK(core_instance->monitors); 03271 cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id"); 03272 return monitor_iter; 03273 }
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 645 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().
00647 { 00648 const char *value = NULL; 00649 00650 if (!strcasecmp(name, "cc_callback_macro")) { 00651 value = ast_get_cc_callback_macro(params); 00652 } else if (!strcasecmp(name, "cc_agent_policy")) { 00653 value = agent_policy_to_str(ast_get_cc_agent_policy(params)); 00654 } else if (!strcasecmp(name, "cc_monitor_policy")) { 00655 value = monitor_policy_to_str(ast_get_cc_monitor_policy(params)); 00656 } else if (!strcasecmp(name, "cc_agent_dialstring")) { 00657 value = ast_get_cc_agent_dialstring(params); 00658 } 00659 if (value) { 00660 ast_copy_string(buf, value, buf_len); 00661 return 0; 00662 } 00663 00664 /* The rest of these are all ints of some sort and require some 00665 * snprintf-itude 00666 */ 00667 00668 if (!strcasecmp(name, "cc_offer_timer")) { 00669 snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params)); 00670 } else if (!strcasecmp(name, "ccnr_available_timer")) { 00671 snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params)); 00672 } else if (!strcasecmp(name, "ccbs_available_timer")) { 00673 snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params)); 00674 } else if (!strcasecmp(name, "cc_max_agents")) { 00675 snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params)); 00676 } else if (!strcasecmp(name, "cc_max_monitors")) { 00677 snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params)); 00678 } else if (!strcasecmp(name, "cc_recall_timer")) { 00679 snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params)); 00680 } else { 00681 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name); 00682 return -1; 00683 } 00684 00685 return 0; 00686 }
int ast_cc_init | ( | void | ) |
Initialize CCSS.
0 | Success | |
nonzero | Failure |
Definition at line 4340 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_register_atexit(), ast_sched_thread_create(), ast_taskprocessor_get(), cc_core_instance_cmp_fn(), cc_core_instance_hash_fn(), cc_shutdown(), cccancel_exec(), ccreq_exec(), generic_monitor_cbs, generic_monitor_cmp_fn(), generic_monitor_hash_fn(), generic_monitors, initialize_cc_max_requests(), and TPS_REF_DEFAULT.
Referenced by main().
04341 { 04342 int res; 04343 04344 if (!(cc_core_instances = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS, 04345 cc_core_instance_hash_fn, cc_core_instance_cmp_fn, 04346 "Create core instance container"))) { 04347 return -1; 04348 } 04349 if (!(generic_monitors = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS, 04350 generic_monitor_hash_fn, generic_monitor_cmp_fn, 04351 "Create generic monitor container"))) { 04352 return -1; 04353 } 04354 if (!(cc_core_taskprocessor = ast_taskprocessor_get("CCSS core", TPS_REF_DEFAULT))) { 04355 return -1; 04356 } 04357 if (!(cc_sched_thread = ast_sched_thread_create())) { 04358 return -1; 04359 } 04360 res = ast_register_application2(ccreq_app, ccreq_exec, NULL, NULL, NULL); 04361 res |= ast_register_application2(cccancel_app, cccancel_exec, NULL, NULL, NULL); 04362 res |= ast_cc_monitor_register(&generic_monitor_cbs); 04363 res |= ast_cc_agent_register(&generic_agent_callbacks); 04364 ast_cli_register_multiple(cc_cli, ARRAY_LEN(cc_cli)); 04365 cc_logger_level = ast_logger_register_level(CC_LOGGER_LEVEL_NAME); 04366 dialed_cc_interface_counter = 1; 04367 initialize_cc_max_requests(); 04368 ast_register_atexit(cc_shutdown); 04369 return res; 04370 }
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 727 of file ccss.c.
Referenced by build_peer(), and process_dahdi().
00728 { 00729 return (!strcasecmp(name, "cc_agent_policy") || 00730 !strcasecmp(name, "cc_monitor_policy") || 00731 !strcasecmp(name, "cc_offer_timer") || 00732 !strcasecmp(name, "ccnr_available_timer") || 00733 !strcasecmp(name, "ccbs_available_timer") || 00734 !strcasecmp(name, "cc_max_agents") || 00735 !strcasecmp(name, "cc_max_monitors") || 00736 !strcasecmp(name, "cc_callback_macro") || 00737 !strcasecmp(name, "cc_agent_dialstring") || 00738 !strcasecmp(name, "cc_recall_timer")); 00739 }
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.
When a CC recall happens, it is important on the called side to know that the call is a CC recall and not a normal call. This function will determine first if the call in question is a CC recall. Then it will determine based on the chan parameter if the channel is being called is being recalled.
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.
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 3172 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, and cc_recall_ds_data::nested.
Referenced by cc_core_init_instance(), sip_call(), and wait_for_answer().
03173 { 03174 struct ast_datastore *recall_datastore; 03175 struct cc_recall_ds_data *recall_data; 03176 struct cc_monitor_tree *interface_tree; 03177 char device_name[AST_CHANNEL_NAME]; 03178 struct ast_cc_monitor *device_monitor; 03179 int core_id_candidate; 03180 03181 ast_assert(core_id != NULL); 03182 03183 *core_id = -1; 03184 03185 ast_channel_lock(chan); 03186 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03187 /* Obviously not a recall if the datastore isn't present */ 03188 ast_channel_unlock(chan); 03189 return 0; 03190 } 03191 03192 recall_data = recall_datastore->data; 03193 03194 if (recall_data->ignore) { 03195 /* Though this is a recall, the call to this particular interface is not part of the 03196 * recall either because this is a call forward or because this is not the first 03197 * invocation of Dial during this call 03198 */ 03199 ast_channel_unlock(chan); 03200 return 0; 03201 } 03202 03203 if (!recall_data->nested) { 03204 /* If the nested flag is not set, then this means that 03205 * the channel passed to this function is the caller making 03206 * the recall. This means that we shouldn't look through 03207 * the monitor tree for the channel because it shouldn't be 03208 * there. However, this is a recall though, so return true. 03209 */ 03210 *core_id = recall_data->core_id; 03211 ast_channel_unlock(chan); 03212 return 1; 03213 } 03214 03215 if (ast_strlen_zero(monitor_type)) { 03216 /* If someone passed a NULL or empty monitor type, then it is clear 03217 * the channel they passed in was an incoming channel, and so searching 03218 * the list of dialed interfaces is not going to be helpful. Just return 03219 * false immediately. 03220 */ 03221 ast_channel_unlock(chan); 03222 return 0; 03223 } 03224 03225 interface_tree = recall_data->interface_tree; 03226 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 03227 /* We grab the value of the recall_data->core_id so that we 03228 * can unlock the channel before we start looking through the 03229 * interface list. That way we don't have to worry about a possible 03230 * clash between the channel lock and the monitor tree lock. 03231 */ 03232 core_id_candidate = recall_data->core_id; 03233 ast_channel_unlock(chan); 03234 03235 /* 03236 * Now we need to find out if the channel device name 03237 * is in the list of interfaces in the called tree. 03238 */ 03239 AST_LIST_LOCK(interface_tree); 03240 AST_LIST_TRAVERSE(interface_tree, device_monitor, next) { 03241 if (!strcmp(device_monitor->interface->device_name, device_name) && 03242 !strcmp(device_monitor->interface->monitor_type, monitor_type)) { 03243 /* BOOM! Device is in the tree! We have a winner! */ 03244 *core_id = core_id_candidate; 03245 AST_LIST_UNLOCK(interface_tree); 03246 return 1; 03247 } 03248 } 03249 AST_LIST_UNLOCK(interface_tree); 03250 return 0; 03251 }
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 3532 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(), and handle_cc_notify().
03533 { 03534 va_list ap; 03535 int res; 03536 03537 va_start(ap, debug); 03538 res = cc_request_state_change(CC_CALLEE_READY, core_id, debug, ap); 03539 va_end(ap); 03540 return res; 03541 }
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 4105 of file ccss.c.
References ao2_t_callback, ast_log_dynamic_level, count_monitors_cb_data::count, count_monitors_cb(), count_monitors_cb_data::device_name, and OBJ_NODATA.
Referenced by ast_queue_cc_frame().
04106 { 04107 struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,}; 04108 04109 ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents"); 04110 ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count); 04111 return data.count; 04112 }
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 a monitor should detect that a failure has occurred when communicating with its endpoint, then ast_cc_monitor_failed should be called. The big difference between ast_cc_monitor_failed and ast_cc_failed is that ast_cc_failed indicates a global failure for a CC transaction, where as ast_cc_monitor_failed is localized to a particular monitor. When ast_cc_failed is called, the entire CC transaction is torn down. When ast_cc_monitor_failed is called, only the monitor on which the failure occurred is pruned from the tree of monitors.
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 3678 of file ccss.c.
References ast_calloc, ast_free, ast_strdup, ast_taskprocessor_push(), ast_vasprintf, cc_monitor_failed(), ast_cc_monitor_failure_data::core_id, ast_cc_monitor_failure_data::debug, and ast_cc_monitor_failure_data::device_name.
Referenced by ast_cc_available_timer_expire(), cc_handle_publish_error(), and handle_response_subscribe().
03679 { 03680 struct ast_cc_monitor_failure_data *failure_data; 03681 int res; 03682 va_list ap; 03683 03684 if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) { 03685 return -1; 03686 } 03687 03688 if (!(failure_data->device_name = ast_strdup(monitor_name))) { 03689 ast_free(failure_data); 03690 return -1; 03691 } 03692 03693 va_start(ap, debug); 03694 if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) { 03695 va_end(ap); 03696 ast_free((char *)failure_data->device_name); 03697 ast_free(failure_data); 03698 return -1; 03699 } 03700 va_end(ap); 03701 03702 failure_data->core_id = core_id; 03703 03704 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_monitor_failed, failure_data); 03705 if (res) { 03706 ast_free((char *)failure_data->device_name); 03707 ast_free((char *)failure_data->debug); 03708 ast_free(failure_data); 03709 } 03710 return res; 03711 }
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 3788 of file ccss.c.
References ast_taskprocessor_push(), cc_party_b_free(), cc_unref(), and find_cc_core_instance().
03789 { 03790 int res; 03791 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03792 03793 if (!core_instance) { 03794 return -1; 03795 } 03796 03797 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_party_b_free, core_instance); 03798 if (res) { 03799 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03800 } 03801 return res; 03802 }
int ast_cc_monitor_register | ( | const struct ast_cc_monitor_callbacks * | callbacks | ) |
Register a set of monitor callbacks with the core.
This is made so that at monitor creation time, the proper callbacks may be installed and the proper .init callback may be called for the monitor to establish private data.
callbacks | The callbacks used by the monitor implementation |
0 | Successfully registered | |
-1 | Failure to register |
Definition at line 895 of file ccss.c.
References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and cc_monitor_backend::callbacks.
Referenced by ast_cc_init(), and load_module().
00896 { 00897 struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend)); 00898 00899 if (!backend) { 00900 return -1; 00901 } 00902 00903 backend->callbacks = callbacks; 00904 00905 AST_RWLIST_WRLOCK(&cc_monitor_backends); 00906 AST_RWLIST_INSERT_TAIL(&cc_monitor_backends, backend, next); 00907 AST_RWLIST_UNLOCK(&cc_monitor_backends); 00908 return 0; 00909 }
int ast_cc_monitor_request_acked | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate that an outbound entity has accepted our CC request.
When we receive confirmation that an outbound device has accepted the CC request we sent it, this function must be called.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3521 of file ccss.c.
References CC_ACTIVE, and cc_request_state_change().
Referenced by cc_generic_monitor_request_cc(), cc_stop_ringing(), and handle_cc_notify().
03522 { 03523 va_list ap; 03524 int res; 03525 03526 va_start(ap, debug); 03527 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap); 03528 va_end(ap); 03529 return res; 03530 }
int ast_cc_monitor_status_request | ( | int | core_id | ) |
Request the status of a caller or callers.
The following are all functions which are required due to the unique case where Asterisk is acting as the NT side of an ISDN PTMP connection to the caller and as the TE side of an ISDN PTMP connection to the callee. In such a case, there are several times where the PTMP monitor needs information from the agent in order to formulate the appropriate messages to send.
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 3723 of file ccss.c.
References ast_taskprocessor_push(), cc_status_request(), cc_unref(), and find_cc_core_instance().
03724 { 03725 int res; 03726 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03727 03728 if (!core_instance) { 03729 return -1; 03730 } 03731 03732 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_request, core_instance); 03733 if (res) { 03734 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03735 } 03736 return res; 03737 }
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 3760 of file ccss.c.
References ast_taskprocessor_push(), cc_stop_ringing(), cc_unref(), and find_cc_core_instance().
03761 { 03762 int res; 03763 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03764 03765 if (!core_instance) { 03766 return -1; 03767 } 03768 03769 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_stop_ringing, core_instance); 03770 if (res) { 03771 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03772 } 03773 return res; 03774 }
void ast_cc_monitor_unregister | ( | const struct ast_cc_monitor_callbacks * | callbacks | ) |
Unregister a set of monitor callbacks with the core.
If a module which makes use of a CC monitor is unloaded, then it may unregister its monitor callbacks with the core.
callbacks | The callbacks used by the monitor implementation |
0 | Successfully unregistered | |
-1 | Failure to unregister |
Definition at line 928 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(), cc_shutdown(), and unload_module().
00929 { 00930 struct cc_monitor_backend *backend; 00931 AST_RWLIST_WRLOCK(&cc_monitor_backends); 00932 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_monitor_backends, backend, next) { 00933 if (backend->callbacks == callbacks) { 00934 AST_RWLIST_REMOVE_CURRENT(next); 00935 ast_free(backend); 00936 break; 00937 } 00938 } 00939 AST_RWLIST_TRAVERSE_SAFE_END; 00940 AST_RWLIST_UNLOCK(&cc_monitor_backends); 00941 }
int ast_cc_offer | ( | struct ast_channel * | caller_chan | ) |
Offer CC to a caller.
This function is called from ast_hangup if the caller is eligible to be offered call completion service.
caller_chan | The calling channel |
-1 | Error | |
0 | Success |
Definition at line 3485 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, and dialed_cc_interfaces::is_original_caller.
Referenced by ast_hangup().
03486 { 03487 int core_id; 03488 int res = -1; 03489 struct ast_datastore *datastore; 03490 struct dialed_cc_interfaces *cc_interfaces; 03491 char cc_is_offerable; 03492 03493 ast_channel_lock(caller_chan); 03494 if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) { 03495 ast_channel_unlock(caller_chan); 03496 return res; 03497 } 03498 03499 cc_interfaces = datastore->data; 03500 cc_is_offerable = cc_interfaces->is_original_caller; 03501 core_id = cc_interfaces->core_id; 03502 ast_channel_unlock(caller_chan); 03503 03504 if (cc_is_offerable) { 03505 res = cc_offer(core_id, "CC offered to caller %s", caller_chan->name); 03506 } 03507 return res; 03508 }
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.
It is recommended that an entity which receives an incoming CC request calls this function before calling ast_cc_agent_accept_request. This way, immediate feedback can be given to the caller about why his request was rejected.
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.
Definition at line 2219 of file ccss.c.
Referenced by cc_caller_requested(), cc_interfaces_datastore_init(), and ccreq_exec().
02220 { 02221 return cc_request_count < global_cc_max_requests; 02222 }
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 688 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(), build_peer(), and process_dahdi().
00690 { 00691 unsigned int value_as_uint; 00692 if (!strcasecmp(name, "cc_agent_policy")) { 00693 return ast_set_cc_agent_policy(params, str_to_agent_policy(value)); 00694 } else if (!strcasecmp(name, "cc_monitor_policy")) { 00695 return ast_set_cc_monitor_policy(params, str_to_monitor_policy(value)); 00696 } else if (!strcasecmp(name, "cc_agent_dialstring")) { 00697 ast_set_cc_agent_dialstring(params, value); 00698 } else if (!strcasecmp(name, "cc_callback_macro")) { 00699 ast_set_cc_callback_macro(params, value); 00700 return 0; 00701 } 00702 00703 if (!sscanf(value, "%30u", &value_as_uint) == 1) { 00704 return -1; 00705 } 00706 00707 if (!strcasecmp(name, "cc_offer_timer")) { 00708 ast_set_cc_offer_timer(params, value_as_uint); 00709 } else if (!strcasecmp(name, "ccnr_available_timer")) { 00710 ast_set_ccnr_available_timer(params, value_as_uint); 00711 } else if (!strcasecmp(name, "ccbs_available_timer")) { 00712 ast_set_ccbs_available_timer(params, value_as_uint); 00713 } else if (!strcasecmp(name, "cc_max_agents")) { 00714 ast_set_cc_max_agents(params, value_as_uint); 00715 } else if (!strcasecmp(name, "cc_max_monitors")) { 00716 ast_set_cc_max_monitors(params, value_as_uint); 00717 } else if (!strcasecmp(name, "cc_recall_timer")) { 00718 ast_set_cc_recall_timer(params, value_as_uint); 00719 } else { 00720 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name); 00721 return -1; 00722 } 00723 00724 return 0; 00725 }
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 840 of file ccss.c.
References ast_cc_config_params::cc_agent_dialstring.
Referenced by ast_cc_get_param(), and generic_recall().
00841 { 00842 return config->cc_agent_dialstring; 00843 }
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 746 of file ccss.c.
References ast_cc_config_params::cc_agent_policy.
Referenced by ast_cc_call_init(), ast_cc_get_param(), build_peer(), cc_core_init_instance(), and find_agent_callbacks().
00747 { 00748 return config->cc_agent_policy; 00749 }
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 874 of file ccss.c.
References ast_cc_config_params::cc_callback_macro.
Referenced by ast_cc_get_param(), and generic_recall().
00875 { 00876 return config->cc_callback_macro; 00877 }
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 854 of file ccss.c.
References ast_cc_config_params::cc_max_agents.
Referenced by ast_cc_get_param(), and cc_core_init_instance().
00855 { 00856 return config->cc_max_agents; 00857 }
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 864 of file ccss.c.
References ast_cc_config_params::cc_max_monitors.
Referenced by ast_cc_get_param(), and ast_queue_cc_frame().
00865 { 00866 return config->cc_max_monitors; 00867 }
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 763 of file ccss.c.
References ast_cc_config_params::cc_monitor_policy.
Referenced by analog_call(), ast_cc_call_failed(), ast_cc_get_param(), dahdi_cc_callback(), and sip_handle_cc().
00764 { 00765 return config->cc_monitor_policy; 00766 }
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 780 of file ccss.c.
References ast_cc_config_params::cc_offer_timer.
Referenced by ast_cc_get_param(), cc_generic_agent_start_offer_timer(), and sip_cc_agent_start_offer_timer().
00781 { 00782 return config->cc_offer_timer; 00783 }
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 810 of file ccss.c.
References ast_cc_config_params::cc_recall_timer.
Referenced by ast_cc_get_param(), and generic_recall().
00811 { 00812 return config->cc_recall_timer; 00813 }
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 825 of file ccss.c.
References ast_cc_config_params::ccbs_available_timer.
Referenced by ast_cc_get_param(), cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().
00826 { 00827 return config->ccbs_available_timer; 00828 }
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 795 of file ccss.c.
References ast_cc_config_params::ccnr_available_timer.
Referenced by ast_cc_get_param(), cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().
00796 { 00797 return config->ccnr_available_timer; 00798 }
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 2048 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, ast_cc_interface::device_name, cc_control_payload::device_name, cc_control_payload::dialstring, ast_cc_monitor::dialstring, EVENT_FLAG_CC, find_cc_core_instance(), dialed_cc_interfaces::ignore, ast_cc_monitor::interface, dialed_cc_interfaces::interface_tree, dialed_cc_interfaces::is_original_caller, LOG_WARNING, manager_event, monitor, cc_control_payload::monitor_type, ast_cc_monitor::parent_id, cc_control_payload::private_data, and cc_control_payload::service.
Referenced by ast_cc_busy_interface(), ast_cc_call_failed(), and wait_for_answer().
02049 { 02050 char *device_name; 02051 char *dialstring; 02052 struct ast_cc_monitor *monitor; 02053 struct ast_datastore *cc_datastore; 02054 struct dialed_cc_interfaces *cc_interfaces; 02055 struct cc_control_payload *cc_data = frame_data; 02056 struct cc_core_instance *core_instance; 02057 02058 device_name = cc_data->device_name; 02059 dialstring = cc_data->dialstring; 02060 02061 ast_channel_lock(inbound); 02062 if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) { 02063 ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name); 02064 ast_channel_unlock(inbound); 02065 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02066 return; 02067 } 02068 02069 cc_interfaces = cc_datastore->data; 02070 02071 if (cc_interfaces->ignore) { 02072 ast_channel_unlock(inbound); 02073 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02074 return; 02075 } 02076 02077 if (!cc_interfaces->is_original_caller) { 02078 /* If the is_original_caller is not set on the *inbound* channel, then 02079 * it must be a local channel. As such, we do not want to create a core instance 02080 * or an agent for the local channel. Instead, we want to pass this along to the 02081 * other side of the local channel so that the original caller can benefit. 02082 */ 02083 ast_channel_unlock(inbound); 02084 ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data)); 02085 return; 02086 } 02087 02088 core_instance = find_cc_core_instance(cc_interfaces->core_id); 02089 if (!core_instance) { 02090 core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree, 02091 cc_interfaces->core_id, cc_data); 02092 if (!core_instance) { 02093 cc_interfaces->ignore = 1; 02094 ast_channel_unlock(inbound); 02095 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02096 return; 02097 } 02098 } 02099 02100 ast_channel_unlock(inbound); 02101 02102 /* Yeah this kind of sucks, but luckily most people 02103 * aren't dialing thousands of interfaces on every call 02104 * 02105 * This traversal helps us to not create duplicate monitors in 02106 * case a device queues multiple CC control frames. 02107 */ 02108 AST_LIST_LOCK(cc_interfaces->interface_tree); 02109 AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) { 02110 if (!strcmp(monitor->interface->device_name, device_name)) { 02111 ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n", 02112 core_instance->core_id, device_name); 02113 AST_LIST_UNLOCK(cc_interfaces->interface_tree); 02114 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance"); 02115 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02116 return; 02117 } 02118 } 02119 AST_LIST_UNLOCK(cc_interfaces->interface_tree); 02120 02121 if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) { 02122 ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name); 02123 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance"); 02124 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02125 return; 02126 } 02127 02128 AST_LIST_LOCK(cc_interfaces->interface_tree); 02129 cc_ref(monitor, "monitor tree's reference to the monitor"); 02130 AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next); 02131 AST_LIST_UNLOCK(cc_interfaces->interface_tree); 02132 02133 cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0); 02134 02135 manager_event(EVENT_FLAG_CC, "CCAvailable", 02136 "CoreID: %d\r\n" 02137 "Callee: %s\r\n" 02138 "Service: %s\r\n", 02139 cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service) 02140 ); 02141 02142 cc_unref(core_instance, "Done with core_instance after handling CC control frame"); 02143 cc_unref(monitor, "Unref reference from allocating monitor"); 02144 }
void ast_ignore_cc | ( | struct ast_channel * | chan | ) |
Mark the channel to ignore further CC activity.
When a CC-capable application, such as Dial, has finished with all CC processing for a channel and knows that any further CC processing should be ignored, this function should be called.
chan | The channel for which further CC processing should be ignored. |
void |
Definition at line 3454 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore::data, cc_recall_ds_data::ignore, and dialed_cc_interfaces::ignore.
Referenced by dial_exec_full(), and do_forward().
03455 { 03456 struct ast_datastore *cc_datastore; 03457 struct ast_datastore *cc_recall_datastore; 03458 struct dialed_cc_interfaces *cc_interfaces; 03459 struct cc_recall_ds_data *recall_cc_data; 03460 03461 ast_channel_lock(chan); 03462 if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) { 03463 cc_interfaces = cc_datastore->data; 03464 cc_interfaces->ignore = 1; 03465 } 03466 03467 if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03468 recall_cc_data = cc_recall_datastore->data; 03469 recall_cc_data->ignore = 1; 03470 } 03471 ast_channel_unlock(chan); 03472 }
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 3886 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(), and sip_handle_cc().
03888 { 03889 struct ast_frame frame = {0,}; 03890 char device_name[AST_CHANNEL_NAME]; 03891 int retval; 03892 struct ast_cc_config_params *cc_params; 03893 03894 cc_params = ast_channel_get_cc_config_params(chan); 03895 if (!cc_params) { 03896 return -1; 03897 } 03898 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 03899 if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) { 03900 ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name); 03901 return -1; 03902 } 03903 03904 if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) { 03905 /* Frame building failed. We can't use this. */ 03906 return -1; 03907 } 03908 retval = ast_queue_frame(chan, &frame); 03909 ast_frfree(&frame); 03910 return retval; 03911 }
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 845 of file ccss.c.
References ast_copy_string(), ast_strlen_zero(), and ast_cc_config_params::cc_agent_dialstring.
Referenced by ast_cc_set_param().
00846 { 00847 if (ast_strlen_zero(value)) { 00848 config->cc_agent_dialstring[0] = '\0'; 00849 } else { 00850 ast_copy_string(config->cc_agent_dialstring, value, sizeof(config->cc_agent_dialstring)); 00851 } 00852 }
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 751 of file ccss.c.
References AST_CC_AGENT_GENERIC, and ast_cc_config_params::cc_agent_policy.
Referenced by ast_cc_set_param(), and build_peer().
00752 { 00753 /* Screw C and its weak type checking for making me have to do this 00754 * validation at runtime. 00755 */ 00756 if (value < AST_CC_AGENT_NEVER || value > AST_CC_AGENT_GENERIC) { 00757 return -1; 00758 } 00759 config->cc_agent_policy = value; 00760 return 0; 00761 }
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 879 of file ccss.c.
References ast_copy_string(), ast_strlen_zero(), and ast_cc_config_params::cc_callback_macro.
Referenced by ast_cc_set_param().
00880 { 00881 if (ast_strlen_zero(value)) { 00882 config->cc_callback_macro[0] = '\0'; 00883 } else { 00884 ast_copy_string(config->cc_callback_macro, value, sizeof(config->cc_callback_macro)); 00885 } 00886 }
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.
The CC_INTERFACES channel variable will have the interfaces that should be called back for a specific PBX instance. This version of the function is used mainly by chan_local, wherein we need to set CC_INTERFACES based on an extension and context that appear in the middle of the tree of dialed interfaces
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 3402 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, pbx_builtin_setvar_helper(), and str.
Referenced by local_call().
03403 { 03404 struct ast_datastore *recall_datastore; 03405 struct cc_monitor_tree *interface_tree; 03406 struct ast_cc_monitor *monitor_iter; 03407 struct cc_recall_ds_data *recall_data; 03408 struct ast_str *str = ast_str_create(64); 03409 int core_id; 03410 03411 if (!str) { 03412 return -1; 03413 } 03414 03415 ast_channel_lock(chan); 03416 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03417 ast_channel_unlock(chan); 03418 ast_free(str); 03419 return -1; 03420 } 03421 recall_data = recall_datastore->data; 03422 interface_tree = recall_data->interface_tree; 03423 core_id = recall_data->core_id; 03424 ast_channel_unlock(chan); 03425 03426 AST_LIST_LOCK(interface_tree); 03427 AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) { 03428 if (!strcmp(monitor_iter->interface->device_name, extension)) { 03429 break; 03430 } 03431 } 03432 03433 if (!monitor_iter) { 03434 /* We couldn't find this extension. This may be because 03435 * we have been directed into an unexpected extension because 03436 * the admin has changed a CC_INTERFACES variable at some point. 03437 */ 03438 AST_LIST_UNLOCK(interface_tree); 03439 ast_free(str); 03440 return -1; 03441 } 03442 03443 build_cc_interfaces_chanvar(monitor_iter, &str); 03444 AST_LIST_UNLOCK(interface_tree); 03445 03446 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str)); 03447 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n", 03448 core_id, ast_str_buffer(str)); 03449 03450 ast_free(str); 03451 return 0; 03452 }
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 859 of file ccss.c.
References ast_cc_config_params::cc_max_agents.
Referenced by ast_cc_set_param().
00860 { 00861 config->cc_max_agents = value; 00862 }
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 869 of file ccss.c.
References ast_cc_config_params::cc_max_monitors.
Referenced by ast_cc_set_param().
00870 { 00871 config->cc_max_monitors = value; 00872 }
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 768 of file ccss.c.
References AST_CC_MONITOR_ALWAYS, and ast_cc_config_params::cc_monitor_policy.
Referenced by ast_cc_set_param().
00769 { 00770 /* Screw C and its weak type checking for making me have to do this 00771 * validation at runtime. 00772 */ 00773 if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) { 00774 return -1; 00775 } 00776 config->cc_monitor_policy = value; 00777 return 0; 00778 }
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 785 of file ccss.c.
References ast_log(), ast_cc_config_params::cc_offer_timer, and LOG_WARNING.
Referenced by ast_cc_set_param().
00786 { 00787 /* 0 is an unreasonable value for any timer. Stick with the default */ 00788 if (value == 0) { 00789 ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer); 00790 return; 00791 } 00792 config->cc_offer_timer = value; 00793 }
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 815 of file ccss.c.
References ast_log(), ast_cc_config_params::cc_recall_timer, and LOG_WARNING.
Referenced by ast_cc_set_param().
00816 { 00817 /* 0 is an unreasonable value for any timer. Stick with the default */ 00818 if (value == 0) { 00819 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->cc_recall_timer); 00820 return; 00821 } 00822 config->cc_recall_timer = value; 00823 }
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 830 of file ccss.c.
References ast_log(), ast_cc_config_params::ccbs_available_timer, and LOG_WARNING.
Referenced by ast_cc_set_param().
00831 { 00832 /* 0 is an unreasonable value for any timer. Stick with the default */ 00833 if (value == 0) { 00834 ast_log(LOG_WARNING, "0 is an invalid value for ccbs_available_timer. Retaining value as %u\n", config->ccbs_available_timer); 00835 return; 00836 } 00837 config->ccbs_available_timer = value; 00838 }
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 800 of file ccss.c.
References ast_log(), ast_cc_config_params::ccnr_available_timer, and LOG_WARNING.
Referenced by ast_cc_set_param().
00801 { 00802 /* 0 is an unreasonable value for any timer. Stick with the default */ 00803 if (value == 0) { 00804 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->ccnr_available_timer); 00805 return; 00806 } 00807 config->ccnr_available_timer = value; 00808 }
int ast_setup_cc_recall_datastore | ( | struct ast_channel * | chan, | |
const int | core_id | |||
) |
Set up a CC recall datastore on a channel.
Implementers of protocol-specific CC agents will need to call this function in order for the channel to have the necessary interfaces to recall.
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 3139 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(), cc_recall_ds_data::core_id, ast_datastore::data, DATASTORE_INHERIT_FOREVER, find_cc_core_instance(), ast_datastore::inheritance, cc_recall_ds_data::interface_tree, and cc_core_instance::monitors.
Referenced by generic_recall(), and handle_request_invite().
03140 { 03141 struct ast_datastore *recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL); 03142 struct cc_recall_ds_data *recall_data; 03143 struct cc_core_instance *core_instance; 03144 03145 if (!recall_datastore) { 03146 return -1; 03147 } 03148 03149 if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) { 03150 ast_datastore_free(recall_datastore); 03151 return -1; 03152 } 03153 03154 if (!(core_instance = find_cc_core_instance(core_id))) { 03155 ast_free(recall_data); 03156 ast_datastore_free(recall_datastore); 03157 return -1; 03158 } 03159 03160 recall_data->interface_tree = cc_ref(core_instance->monitors, 03161 "Bump refcount for monitor tree for recall datastore"); 03162 recall_data->core_id = core_id; 03163 recall_datastore->data = recall_data; 03164 recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER; 03165 ast_channel_lock(chan); 03166 ast_channel_datastore_add(chan, recall_datastore); 03167 ast_channel_unlock(chan); 03168 cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref"); 03169 return 0; 03170 }
static void build_cc_interfaces_chanvar | ( | struct ast_cc_monitor * | starting_point, | |
struct ast_str ** | str | |||
) | [static] |
Definition at line 3322 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, extension_child_dialstring::original_dialstring, ast_cc_monitor::parent_id, and ast_cc_monitor::private_data.
Referenced by ast_cc_agent_set_interfaces_chanvar(), and ast_set_cc_interfaces_chanvar().
03323 { 03324 struct extension_monitor_pvt *extension_pvt; 03325 struct extension_child_dialstring *child_dialstring; 03326 struct ast_cc_monitor *monitor_iter = starting_point; 03327 int top_level_id = starting_point->id; 03328 size_t length; 03329 03330 /* Init to an empty string. */ 03331 ast_str_truncate(*str, 0); 03332 03333 /* First we need to take all of the is_valid child_dialstrings from 03334 * the extension monitor we found and add them to the CC_INTERFACES 03335 * chanvar 03336 */ 03337 extension_pvt = starting_point->private_data; 03338 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) { 03339 if (child_dialstring->is_valid) { 03340 cc_unique_append(str, child_dialstring->original_dialstring); 03341 } 03342 } 03343 03344 /* And now we get the dialstrings from each of the device monitors */ 03345 while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) { 03346 if (monitor_iter->parent_id == top_level_id) { 03347 cc_unique_append(str, monitor_iter->dialstring); 03348 } 03349 } 03350 03351 /* str will have an extra '&' tacked onto the end of it, so we need 03352 * to get rid of that. 03353 */ 03354 length = ast_str_strlen(*str); 03355 if (length) { 03356 ast_str_truncate(*str, length - 1); 03357 } 03358 if (length <= 1) { 03359 /* Nothing to recall? This should not happen. */ 03360 ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n", 03361 starting_point->interface->device_name); 03362 } 03363 }
static void call_destructor_with_no_monitor | ( | const char *const | monitor_type, | |
void * | private_data | |||
) | [static] |
Definition at line 1946 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().
01947 { 01948 const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type); 01949 01950 if (!monitor_callbacks) { 01951 return; 01952 } 01953 01954 monitor_callbacks->destructor(private_data); 01955 }
static void cancel_available_timer | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2955 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, ast_cc_interface::device_name, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, and ast_cc_monitor::parent_id.
Referenced by cc_recalling().
02956 { 02957 struct ast_cc_monitor *monitor_iter; 02958 AST_LIST_LOCK(core_instance->monitors); 02959 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02960 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02961 if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) { 02962 AST_LIST_REMOVE_CURRENT(next); 02963 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02964 monitor_iter->interface->device_name, 1); 02965 cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor"); 02966 } 02967 } 02968 } 02969 AST_LIST_TRAVERSE_SAFE_END; 02970 02971 if (!has_device_monitors(core_instance)) { 02972 ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers"); 02973 } 02974 AST_LIST_UNLOCK(core_instance->monitors); 02975 }
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 2888 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().
02889 { 02890 /* Either 02891 * 1. Callee accepted CC request, call agent's ack callback. 02892 * 2. Caller became available, call agent's stop_monitoring callback and 02893 * call monitor's unsuspend callback. 02894 */ 02895 if (previous_state == CC_CALLER_REQUESTED) { 02896 core_instance->agent->callbacks->respond(core_instance->agent, 02897 AST_CC_AGENT_RESPONSE_SUCCESS); 02898 manager_event(EVENT_FLAG_CC, "CCRequestAcknowledged", 02899 "CoreID: %d\r\n" 02900 "Caller: %s\r\n", 02901 core_instance->core_id, core_instance->agent->device_name); 02902 } else if (previous_state == CC_CALLER_BUSY) { 02903 manager_event(EVENT_FLAG_CC, "CCCallerStopMonitoring", 02904 "CoreID: %d\r\n" 02905 "Caller: %s\r\n", 02906 core_instance->core_id, core_instance->agent->device_name); 02907 unsuspend(core_instance); 02908 } 02909 /* Not possible for previous_state to be anything else due to the is_state_change_valid check at the beginning */ 02910 return 0; 02911 }
static int cc_agent_callback_helper | ( | void * | obj, | |
void * | args, | |||
int | flags | |||
) | [static] |
Definition at line 434 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().
00435 { 00436 struct cc_core_instance *core_instance = obj; 00437 struct cc_callback_helper *helper = args; 00438 00439 if (strcmp(core_instance->agent->callbacks->type, helper->type)) { 00440 return 0; 00441 } 00442 00443 return helper->function(core_instance->agent, helper->args, flags); 00444 }
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, read] |
Definition at line 2291 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, ast_cc_agent::callbacks, ast_cc_agent::cc_params, cc_unref(), check_callback_sanity(), ast_cc_agent::core_id, ast_cc_agent::device_name, find_agent_callbacks(), and ast_cc_agent_callbacks::init.
Referenced by cc_core_init_instance().
02294 { 02295 struct ast_cc_agent *agent; 02296 struct ast_cc_config_params *cc_params; 02297 02298 if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy, 02299 "Allocating new ast_cc_agent"))) { 02300 return NULL; 02301 } 02302 02303 agent->core_id = core_id; 02304 strcpy(agent->device_name, caller_name); 02305 02306 cc_params = ast_channel_get_cc_config_params(caller_chan); 02307 if (!cc_params) { 02308 cc_unref(agent, "Could not get channel config params."); 02309 return NULL; 02310 } 02311 if (!(agent->cc_params = ast_cc_config_params_init())) { 02312 cc_unref(agent, "Could not init agent config params."); 02313 return NULL; 02314 } 02315 ast_cc_copy_config_params(agent->cc_params, cc_params); 02316 02317 if (!(agent->callbacks = find_agent_callbacks(caller_chan))) { 02318 cc_unref(agent, "Could not find agent callbacks."); 02319 return NULL; 02320 } 02321 check_callback_sanity(agent->callbacks); 02322 02323 if (agent->callbacks->init(agent, caller_chan)) { 02324 cc_unref(agent, "Agent init callback failed."); 02325 return NULL; 02326 } 02327 ast_log_dynamic_level(cc_logger_level, "Core %d: Created an agent for caller %s\n", 02328 agent->core_id, agent->device_name); 02329 return agent; 02330 }
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 2769 of file ccss.c.
References ast_log(), and LOG_WARNING.
02770 { 02771 /* This should never happen... */ 02772 ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n"); 02773 return -1; 02774 }
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 3858 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, 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().
03861 { 03862 struct ast_datastore *datastore; 03863 struct dialed_cc_interfaces *cc_interfaces; 03864 int dial_parent_id; 03865 03866 ast_channel_lock(chan); 03867 datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL); 03868 if (!datastore) { 03869 ast_channel_unlock(chan); 03870 return -1; 03871 } 03872 cc_interfaces = datastore->data; 03873 dial_parent_id = cc_interfaces->dial_parent_id; 03874 ast_channel_unlock(chan); 03875 03876 payload->monitor_type = monitor_type; 03877 payload->private_data = private_data; 03878 payload->service = service; 03879 ast_cc_copy_config_params(&payload->config_params, cc_params); 03880 payload->parent_interface_id = dial_parent_id; 03881 ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name)); 03882 ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring)); 03883 return 0; 03884 }
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 2913 of file ccss.c.
References cc_core_instance::agent, ast_cc_agent::callbacks, and ast_cc_agent_callbacks::callee_available.
02914 { 02915 core_instance->agent->callbacks->callee_available(core_instance->agent); 02916 return 0; 02917 }
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 2941 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().
02942 { 02943 /* Callee was available, but caller was busy, call agent's begin_monitoring callback 02944 * and call monitor's suspend callback. 02945 */ 02946 suspend(core_instance); 02947 core_instance->agent->callbacks->start_monitoring(core_instance->agent); 02948 manager_event(EVENT_FLAG_CC, "CCCallerStartMonitoring", 02949 "CoreID: %d\r\n" 02950 "Caller: %s\r\n", 02951 core_instance->core_id, core_instance->agent->device_name); 02952 return 0; 02953 }
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 2776 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.
02777 { 02778 if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) { 02779 ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n", 02780 core_instance->agent->device_name); 02781 return -1; 02782 } 02783 manager_event(EVENT_FLAG_CC, "CCOfferTimerStart", 02784 "CoreID: %d\r\n" 02785 "Caller: %s\r\n" 02786 "Expires: %u\r\n", 02787 core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer); 02788 ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n", 02789 core_instance->core_id, core_instance->agent->device_name); 02790 return 0; 02791 }
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 2852 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.
02853 { 02854 if (!ast_cc_request_is_within_limits()) { 02855 ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n"); 02856 core_instance->agent->callbacks->respond(core_instance->agent, 02857 AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY); 02858 ast_cc_failed(core_instance->core_id, "Too many requests in the system"); 02859 return -1; 02860 } 02861 core_instance->agent->callbacks->stop_offer_timer(core_instance->agent); 02862 request_cc(core_instance); 02863 return 0; 02864 }
static int cc_cli_output_status | ( | void * | data | ) | [static] |
Definition at line 4178 of file ccss.c.
References ao2_container_count(), ao2_t_callback, ast_cli(), ast_free, OBJ_NODATA, and print_stats_cb().
Referenced by handle_cc_status().
04179 { 04180 int *cli_fd = data; 04181 int count = ao2_container_count(cc_core_instances); 04182 04183 if (!count) { 04184 ast_cli(*cli_fd, "There are currently no active call completion transactions\n"); 04185 } else { 04186 ast_cli(*cli_fd, "%d Call completion transactions\n", count); 04187 ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n"); 04188 ast_cli(*cli_fd, "----------------------------------------------------------------------------\n"); 04189 ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI"); 04190 } 04191 ast_free(cli_fd); 04192 return 0; 04193 }
static void cc_cli_print_monitor_stats | ( | struct ast_cc_monitor * | monitor, | |
int | fd, | |||
int | parent_id | |||
) | [static] |
Definition at line 4145 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cli(), AST_LIST_NEXT, cc_service_to_string(), ast_cc_interface::device_name, ast_cc_monitor::id, ast_cc_monitor::interface, ast_cc_interface::monitor_class, ast_cc_monitor::parent_id, and ast_cc_monitor::service_offered.
Referenced by print_stats_cb().
04146 { 04147 struct ast_cc_monitor *child_monitor_iter = monitor; 04148 if (!monitor) { 04149 return; 04150 } 04151 04152 ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name); 04153 if (monitor->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 04154 ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered)); 04155 } 04156 ast_cli(fd, "\n"); 04157 04158 while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) { 04159 if (child_monitor_iter->parent_id == monitor->id) { 04160 cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id); 04161 } 04162 } 04163 }
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 2989 of file ccss.c.
References cc_core_instance::agent, ao2_t_unlink, cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, and manager_event.
02990 { 02991 /* Recall has made progress, call agent and monitor destructor functions 02992 */ 02993 manager_event(EVENT_FLAG_CC, "CCRecallComplete", 02994 "CoreID: %d\r\n" 02995 "Caller: %s\r\n", 02996 core_instance->core_id, core_instance->agent->device_name); 02997 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed"); 02998 return 0; 02999 }
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, read] |
Definition at line 2652 of file ccss.c.
References cc_core_instance::agent, 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_ref(), cc_unref(), cc_core_instance::core_id, count_agents(), kill_duplicate_offers(), and cc_core_instance::monitors.
Referenced by ast_handle_cc_control_frame().
02654 { 02655 char caller[AST_CHANNEL_NAME]; 02656 struct cc_core_instance *core_instance; 02657 struct ast_cc_config_params *cc_params; 02658 long agent_count; 02659 int recall_core_id; 02660 02661 ast_channel_get_device_name(caller_chan, caller, sizeof(caller)); 02662 cc_params = ast_channel_get_cc_config_params(caller_chan); 02663 if (!cc_params) { 02664 ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n", 02665 caller); 02666 return NULL; 02667 } 02668 /* First, we need to kill off other pending CC offers from caller. If the caller is going 02669 * to request a CC service, it may only be for the latest call he made. 02670 */ 02671 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) { 02672 kill_duplicate_offers(caller); 02673 } 02674 02675 ast_cc_is_recall(caller_chan, &recall_core_id, NULL); 02676 agent_count = count_agents(caller, recall_core_id); 02677 if (agent_count >= ast_get_cc_max_agents(cc_params)) { 02678 ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller); 02679 return NULL; 02680 } 02681 02682 /* Generic agents can only have a single outstanding CC request per caller. */ 02683 if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) { 02684 ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n"); 02685 return NULL; 02686 } 02687 02688 /* Next, we need to create the core instance for this call */ 02689 if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) { 02690 return NULL; 02691 } 02692 02693 core_instance->core_id = core_id; 02694 if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) { 02695 cc_unref(core_instance, "Couldn't allocate agent, unref core_instance"); 02696 return NULL; 02697 } 02698 02699 core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree"); 02700 02701 ao2_t_link(cc_core_instances, core_instance, "Link core instance into container"); 02702 02703 return core_instance; 02704 }
static int cc_core_instance_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 413 of file ccss.c.
References CMP_MATCH, CMP_STOP, and cc_core_instance::core_id.
Referenced by ast_cc_init().
00414 { 00415 struct cc_core_instance *core_instance1 = obj; 00416 struct cc_core_instance *core_instance2 = arg; 00417 00418 return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0; 00419 }
static void cc_core_instance_destructor | ( | void * | data | ) | [static] |
Definition at line 2640 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().
02641 { 02642 struct cc_core_instance *core_instance = data; 02643 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id); 02644 if (core_instance->agent) { 02645 cc_unref(core_instance->agent, "Core instance is done with the agent now"); 02646 } 02647 if (core_instance->monitors) { 02648 core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list"); 02649 } 02650 }
static int cc_core_instance_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 407 of file ccss.c.
References cc_core_instance::core_id.
Referenced by ast_cc_init().
00408 { 00409 const struct cc_core_instance *core_instance = obj; 00410 return core_instance->core_id; 00411 }
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, read] |
Definition at line 1982 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, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, cc_interface_destroy(), cc_monitor_destroy(), cc_unref(), cc_control_payload::config_params, ast_cc_interface::config_params, ast_cc_monitor::core_id, ast_cc_interface::device_name, ast_cc_monitor::dialstring, find_monitor_callbacks(), ast_cc_monitor::id, ast_cc_monitor::interface, monitor, ast_cc_interface::monitor_class, ast_cc_interface::monitor_type, cc_control_payload::monitor_type, ast_cc_monitor::parent_id, cc_control_payload::parent_interface_id, cc_control_payload::private_data, ast_cc_monitor::private_data, cc_control_payload::service, and ast_cc_monitor::service_offered.
Referenced by ast_handle_cc_control_frame().
01983 { 01984 struct ast_cc_interface *cc_interface; 01985 struct ast_cc_monitor *monitor; 01986 size_t device_name_len = strlen(device_name); 01987 int parent_id = cc_data->parent_interface_id; 01988 01989 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy, 01990 "Allocating new ast_cc_interface"))) { 01991 return NULL; 01992 } 01993 01994 if (!(cc_interface->config_params = ast_cc_config_params_init())) { 01995 cc_unref(cc_interface, "Failed to allocate config params, unref interface"); 01996 return NULL; 01997 } 01998 01999 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) { 02000 cc_unref(cc_interface, "Failed to allocate monitor, unref interface"); 02001 return NULL; 02002 } 02003 02004 if (!(monitor->dialstring = ast_strdup(dialstring))) { 02005 cc_unref(monitor, "Failed to copy dialable name. Unref monitor"); 02006 cc_unref(cc_interface, "Failed to copy dialable name"); 02007 return NULL; 02008 } 02009 02010 if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) { 02011 cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor"); 02012 cc_unref(cc_interface, "Failed to find monitor callbacks"); 02013 return NULL; 02014 } 02015 02016 strcpy(cc_interface->device_name, device_name); 02017 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1); 02018 monitor->parent_id = parent_id; 02019 monitor->core_id = core_id; 02020 monitor->service_offered = cc_data->service; 02021 monitor->private_data = cc_data->private_data; 02022 cc_interface->monitor_type = cc_data->monitor_type; 02023 cc_interface->monitor_class = AST_CC_DEVICE_MONITOR; 02024 monitor->interface = cc_interface; 02025 monitor->available_timer_id = -1; 02026 ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params); 02027 ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %d and parent %d\n", 02028 monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id); 02029 return monitor; 02030 }
static int cc_do_state_change | ( | void * | datap | ) | [static] |
Definition at line 3024 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_state_change_args::core_id, cc_state_change_args::core_instance, cc_core_instance::current_state, cc_state_change_args::debug, is_state_change_valid(), ast_cc_agent_callbacks::respond, cc_state_change_args::state, and state_change_funcs.
Referenced by cc_request_state_change().
03025 { 03026 struct cc_state_change_args *args = datap; 03027 struct cc_core_instance *core_instance; 03028 enum cc_state previous_state; 03029 int res; 03030 03031 ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %d requested. Reason: %s\n", 03032 args->core_id, args->state, args->debug); 03033 03034 core_instance = args->core_instance; 03035 03036 if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) { 03037 ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n", 03038 args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state)); 03039 if (args->state == CC_CALLER_REQUESTED) { 03040 /* 03041 * For out-of-order requests, we need to let the requester know that 03042 * we can't handle the request now. 03043 */ 03044 core_instance->agent->callbacks->respond(core_instance->agent, 03045 AST_CC_AGENT_RESPONSE_FAILURE_INVALID); 03046 } 03047 ast_free(args); 03048 cc_unref(core_instance, "Unref core instance from when it was found earlier"); 03049 return -1; 03050 } 03051 03052 /* We can change to the new state now. */ 03053 previous_state = core_instance->current_state; 03054 core_instance->current_state = args->state; 03055 res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state); 03056 03057 ast_free(args); 03058 cc_unref(core_instance, "Unref since state change has completed"); /* From ao2_find */ 03059 return res; 03060 }
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 1780 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, and ast_cc_monitor::private_data.
Referenced by ast_handle_cc_control_frame(), cancel_available_timer(), cc_monitor_failed(), request_cc(), suspend(), and unsuspend().
01781 { 01782 struct ast_cc_monitor *monitor_iter; 01783 struct extension_monitor_pvt *extension_pvt; 01784 struct extension_child_dialstring *child_dialstring; 01785 01786 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 01787 if (monitor_iter->id == parent_id) { 01788 break; 01789 } 01790 } 01791 01792 if (!monitor_iter) { 01793 return; 01794 } 01795 extension_pvt = monitor_iter->private_data; 01796 01797 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) { 01798 if (!strcmp(child_dialstring->device_name, device_name)) { 01799 child_dialstring->is_valid = is_valid; 01800 break; 01801 } 01802 } 01803 }
static void cc_extension_monitor_destructor | ( | void * | private_data | ) | [static] |
Definition at line 1551 of file ccss.c.
References ast_free, AST_LIST_REMOVE_HEAD, and extension_monitor_pvt::child_dialstrings.
Referenced by cc_monitor_destroy().
01552 { 01553 struct extension_monitor_pvt *extension_pvt = private_data; 01554 struct extension_child_dialstring *child_dialstring; 01555 01556 /* This shouldn't be possible, but I'm paranoid */ 01557 if (!extension_pvt) { 01558 return; 01559 } 01560 01561 while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) { 01562 ast_free(child_dialstring); 01563 } 01564 ast_free(extension_pvt); 01565 }
static struct ast_cc_monitor* cc_extension_monitor_init | ( | const char *const | exten, | |
const char *const | context, | |||
const unsigned int | parent_id | |||
) | [static, read] |
Definition at line 1819 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(), ast_cc_interface::device_name, extension_monitor_pvt_init(), ast_cc_monitor::id, ast_cc_monitor::interface, monitor, ast_cc_interface::monitor_class, ast_cc_interface::monitor_type, ast_cc_monitor::parent_id, ast_cc_monitor::private_data, and str.
Referenced by ast_cc_call_init(), and cc_interfaces_datastore_init().
01820 { 01821 struct ast_str *str = ast_str_alloca(2 * AST_MAX_EXTENSION); 01822 struct ast_cc_interface *cc_interface; 01823 struct ast_cc_monitor *monitor; 01824 01825 ast_str_set(&str, 0, "%s@%s", exten, context); 01826 01827 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy, 01828 "Allocating new ast_cc_interface"))) { 01829 return NULL; 01830 } 01831 01832 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) { 01833 cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface"); 01834 return NULL; 01835 } 01836 01837 if (!(monitor->private_data = extension_monitor_pvt_init())) { 01838 cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor"); 01839 cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface"); 01840 } 01841 01842 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1); 01843 monitor->parent_id = parent_id; 01844 cc_interface->monitor_type = "extension"; 01845 cc_interface->monitor_class = AST_CC_EXTENSION_MONITOR; 01846 strcpy(cc_interface->device_name, ast_str_buffer(str)); 01847 monitor->interface = cc_interface; 01848 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); 01849 return monitor; 01850 }
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 3001 of file ccss.c.
References cc_core_instance::agent, ao2_t_unlink, cc_core_instance::core_id, cc_state_change_args::debug, ast_cc_agent::device_name, EVENT_FLAG_CC, and manager_event.
03002 { 03003 manager_event(EVENT_FLAG_CC, "CCFailure", 03004 "CoreID: %d\r\n" 03005 "Caller: %s\r\n" 03006 "Reason: %s\r\n", 03007 core_instance->core_id, core_instance->agent->device_name, args->debug); 03008 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed"); 03009 return 0; 03010 }
static void cc_generic_agent_destructor | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2623 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.
02624 { 02625 struct cc_generic_agent_pvt *agent_pvt = agent->private_data; 02626 02627 if (!agent_pvt) { 02628 /* The agent constructor probably failed. */ 02629 return; 02630 } 02631 02632 cc_generic_agent_stop_offer_timer(agent); 02633 if (agent_pvt->sub) { 02634 agent_pvt->sub = ast_event_unsubscribe(agent_pvt->sub); 02635 } 02636 02637 ast_free(agent_pvt); 02638 }
static int cc_generic_agent_init | ( | struct ast_cc_agent * | agent, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 2406 of file ccss.c.
References ast_calloc, AST_CC_AGENT_SKIP_OFFER, ast_copy_string(), ast_set_flag, ast_channel::caller, cc_generic_agent_pvt::cid_name, cc_generic_agent_pvt::cid_num, ast_channel::context, cc_generic_agent_pvt::context, ast_channel::exten, cc_generic_agent_pvt::exten, ast_party_caller::id, ast_channel::macrocontext, ast_channel::macroexten, ast_party_id::name, ast_party_id::number, cc_generic_agent_pvt::offer_timer_id, ast_cc_agent::private_data, S_OR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
02407 { 02408 struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt)); 02409 02410 if (!generic_pvt) { 02411 return -1; 02412 } 02413 02414 generic_pvt->offer_timer_id = -1; 02415 if (chan->caller.id.number.valid && chan->caller.id.number.str) { 02416 ast_copy_string(generic_pvt->cid_num, chan->caller.id.number.str, sizeof(generic_pvt->cid_num)); 02417 } 02418 if (chan->caller.id.name.valid && chan->caller.id.name.str) { 02419 ast_copy_string(generic_pvt->cid_name, chan->caller.id.name.str, sizeof(generic_pvt->cid_name)); 02420 } 02421 ast_copy_string(generic_pvt->exten, S_OR(chan->macroexten, chan->exten), sizeof(generic_pvt->exten)); 02422 ast_copy_string(generic_pvt->context, S_OR(chan->macrocontext, chan->context), sizeof(generic_pvt->context)); 02423 agent->private_data = generic_pvt; 02424 ast_set_flag(agent, AST_CC_AGENT_SKIP_OFFER); 02425 return 0; 02426 }
static int cc_generic_agent_recall | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2607 of file ccss.c.
References ast_cc_agent_caller_busy(), ast_pthread_create_detached_background, cc_generic_is_device_available(), ast_cc_agent::core_id, ast_cc_agent::device_name, and generic_recall().
02608 { 02609 pthread_t clotho; 02610 enum ast_device_state current_state = ast_device_state(agent->device_name); 02611 02612 if (!cc_generic_is_device_available(current_state)) { 02613 /* We can't try to contact the device right now because he's not available 02614 * Let the core know he's busy. 02615 */ 02616 ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name); 02617 return 0; 02618 } 02619 ast_pthread_create_detached_background(&clotho, NULL, generic_recall, agent); 02620 return 0; 02621 }
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 2529 of file ccss.c.
References ast_assert, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, 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.
02530 { 02531 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02532 struct ast_str *str = ast_str_alloca(128); 02533 02534 ast_assert(generic_pvt->sub == NULL); 02535 ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n", 02536 agent->device_name); 02537 02538 if (!(generic_pvt->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, 02539 generic_agent_devstate_cb, ast_str_buffer(str), agent, 02540 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, agent->device_name, 02541 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_EXISTS, 02542 AST_EVENT_IE_END))) { 02543 return -1; 02544 } 02545 return 0; 02546 }
static int cc_generic_agent_start_offer_timer | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2440 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(), ast_cc_agent::core_id, offer_timer_expire(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.
02441 { 02442 int when; 02443 int sched_id; 02444 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02445 02446 ast_assert(cc_sched_thread != NULL); 02447 ast_assert(agent->cc_params != NULL); 02448 02449 when = ast_get_cc_offer_timer(agent->cc_params) * 1000; 02450 ast_log_dynamic_level(cc_logger_level, "Core %d: About to schedule offer timer expiration for %d ms\n", 02451 agent->core_id, when); 02452 if ((sched_id = ast_sched_thread_add(cc_sched_thread, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) { 02453 return -1; 02454 } 02455 generic_pvt->offer_timer_id = sched_id; 02456 return 0; 02457 }
static int cc_generic_agent_status_request | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2480 of file ccss.c.
References ast_cc_agent_status_response(), ast_cc_agent::core_id, and ast_cc_agent::device_name.
02481 { 02482 ast_cc_agent_status_response(agent->core_id, ast_device_state(agent->device_name)); 02483 return 0; 02484 }
static int cc_generic_agent_stop_offer_timer | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2459 of file ccss.c.
References ast_sched_thread_del, cc_unref(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.
Referenced by cc_generic_agent_destructor().
02460 { 02461 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02462 02463 if (generic_pvt->offer_timer_id != -1) { 02464 if (!ast_sched_thread_del(cc_sched_thread, generic_pvt->offer_timer_id)) { 02465 cc_unref(agent, "Remove scheduler's reference to the agent"); 02466 } 02467 generic_pvt->offer_timer_id = -1; 02468 } 02469 return 0; 02470 }
static int cc_generic_agent_stop_ringing | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2486 of file ccss.c.
References ast_channel_get_by_name_prefix(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, and ast_cc_agent::device_name.
02487 { 02488 struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name)); 02489 02490 if (!recall_chan) { 02491 return 0; 02492 } 02493 02494 ast_softhangup(recall_chan, AST_SOFTHANGUP_EXPLICIT); 02495 return 0; 02496 }
static int cc_generic_is_device_available | ( | enum ast_device_state | state | ) | [static] |
Definition at line 1024 of file ccss.c.
References AST_DEVICE_NOT_INUSE, and AST_DEVICE_UNKNOWN.
Referenced by cc_generic_agent_recall(), cc_generic_monitor_destructor(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), generic_agent_devstate_cb(), and generic_monitor_devstate_tp_cb().
01025 { 01026 return state == AST_DEVICE_NOT_INUSE || state == AST_DEVICE_UNKNOWN; 01027 }
static int cc_generic_monitor_cancel_available_timer | ( | struct ast_cc_monitor * | monitor, | |
int * | sched_id | |||
) | [static] |
Definition at line 1381 of file ccss.c.
References ast_assert, ast_log_dynamic_level, ast_sched_thread_del, cc_unref(), ast_cc_monitor::core_id, ast_cc_interface::device_name, and ast_cc_monitor::interface.
01382 { 01383 ast_assert(sched_id != NULL); 01384 01385 if (*sched_id == -1) { 01386 return 0; 01387 } 01388 01389 ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n", 01390 monitor->core_id, monitor->interface->device_name); 01391 if (!ast_sched_thread_del(cc_sched_thread, *sched_id)) { 01392 cc_unref(monitor, "Remove scheduler's reference to the monitor"); 01393 } 01394 *sched_id = -1; 01395 return 0; 01396 }
static void cc_generic_monitor_destructor | ( | void * | private_data | ) | [static] |
Definition at line 1398 of file ccss.c.
References ao2_t_unlink, ast_cc_monitor_callee_available(), 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_generic_is_device_available(), 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, and generic_monitor_instance::monitoring.
01399 { 01400 struct generic_monitor_pvt *gen_mon_pvt = private_data; 01401 struct generic_monitor_instance_list *generic_list; 01402 struct generic_monitor_instance *generic_instance; 01403 01404 if (!private_data) { 01405 /* If the private data is NULL, that means that the monitor hasn't even 01406 * been created yet, but that the destructor was called. While this sort 01407 * of behavior is useful for native monitors, with a generic one, there is 01408 * nothing in particular to do. 01409 */ 01410 return; 01411 } 01412 01413 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n", 01414 gen_mon_pvt->core_id, gen_mon_pvt->device_name); 01415 01416 if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) { 01417 /* If there's no generic list, that means that the monitor is being destroyed 01418 * before we actually got to request CC. Not a biggie. Same in the situation 01419 * below if the list traversal should complete without finding an entry. 01420 */ 01421 ast_free((char *)gen_mon_pvt->device_name); 01422 ast_free(gen_mon_pvt); 01423 return; 01424 } 01425 01426 AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) { 01427 if (generic_instance->core_id == gen_mon_pvt->core_id) { 01428 AST_LIST_REMOVE_CURRENT(next); 01429 ast_free(generic_instance); 01430 break; 01431 } 01432 } 01433 AST_LIST_TRAVERSE_SAFE_END; 01434 01435 if (AST_LIST_EMPTY(&generic_list->list)) { 01436 /* No more monitors with this device name exist. Time to unlink this 01437 * list from the container 01438 */ 01439 ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container"); 01440 } else { 01441 /* There are still instances for this particular device. The situation 01442 * may be that we were attempting a CC recall and a failure occurred, perhaps 01443 * on the agent side. If a failure happens here and the device being monitored 01444 * is available, then we need to signal on the first unsuspended instance that 01445 * the device is available for recall. 01446 */ 01447 01448 /* First things first. We don't even want to consider this action if 01449 * the device in question isn't available right now. 01450 */ 01451 if (generic_list->fit_for_recall 01452 && cc_generic_is_device_available(generic_list->current_state)) { 01453 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01454 if (!generic_instance->is_suspended && generic_instance->monitoring) { 01455 ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor " 01456 "availability due to other instance's failure."); 01457 break; 01458 } 01459 } 01460 } 01461 } 01462 cc_unref(generic_list, "Done with generic list in generic monitor destructor"); 01463 ast_free((char *)gen_mon_pvt->device_name); 01464 ast_free(gen_mon_pvt); 01465 }
static int cc_generic_monitor_request_cc | ( | struct ast_cc_monitor * | monitor, | |
int * | available_timer_id | |||
) | [static] |
Definition at line 1249 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_unref(), ast_cc_interface::config_params, generic_monitor_instance::core_id, ast_cc_monitor::core_id, generic_monitor_pvt::core_id, create_new_generic_list(), ast_cc_interface::device_name, generic_monitor_pvt::device_name, find_generic_monitor_instance_list(), generic_monitor_instance_list::fit_for_recall, ast_cc_monitor::interface, generic_monitor_instance_list::list, generic_monitor_instance::monitoring, ast_cc_monitor::private_data, service, and ast_cc_monitor::service_offered.
01250 { 01251 struct generic_monitor_instance_list *generic_list; 01252 struct generic_monitor_instance *generic_instance; 01253 struct generic_monitor_pvt *gen_mon_pvt; 01254 enum ast_cc_service_type service = monitor->service_offered; 01255 int when; 01256 01257 /* First things first. Native channel drivers will have their private data allocated 01258 * at the time that they tell the core that they can offer CC. Generic is quite a bit 01259 * different, and we wait until this point to allocate our private data. 01260 */ 01261 if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) { 01262 return -1; 01263 } 01264 01265 if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) { 01266 ast_free(gen_mon_pvt); 01267 return -1; 01268 } 01269 01270 gen_mon_pvt->core_id = monitor->core_id; 01271 01272 monitor->private_data = gen_mon_pvt; 01273 01274 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) { 01275 if (!(generic_list = create_new_generic_list(monitor))) { 01276 return -1; 01277 } 01278 } 01279 01280 if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) { 01281 /* The generic monitor destructor will take care of the appropriate 01282 * deallocations 01283 */ 01284 cc_unref(generic_list, "Generic monitor instance failed to allocate"); 01285 return -1; 01286 } 01287 generic_instance->core_id = monitor->core_id; 01288 generic_instance->monitoring = 1; 01289 AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next); 01290 when = service == AST_CC_CCBS ? ast_get_ccbs_available_timer(monitor->interface->config_params) : 01291 ast_get_ccnr_available_timer(monitor->interface->config_params); 01292 01293 *available_timer_id = ast_sched_thread_add(cc_sched_thread, when * 1000, 01294 ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference")); 01295 if (*available_timer_id == -1) { 01296 cc_unref(monitor, "Failed to schedule available timer. (monitor)"); 01297 cc_unref(generic_list, "Failed to schedule available timer. (generic_list)"); 01298 return -1; 01299 } 01300 /* If the new instance was created as CCNR, then that means this device is not currently 01301 * fit for recall even if it previously was. 01302 */ 01303 if (service == AST_CC_CCNR || service == AST_CC_CCNL) { 01304 generic_list->fit_for_recall = 0; 01305 } 01306 ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.", 01307 monitor->interface->device_name); 01308 cc_unref(generic_list, "Finished with monitor instance reference in request cc callback"); 01309 return 0; 01310 }
static int cc_generic_monitor_suspend | ( | struct ast_cc_monitor * | monitor | ) | [static] |
Definition at line 1312 of file ccss.c.
References ast_cc_monitor_callee_available(), AST_LIST_TRAVERSE, cc_generic_is_device_available(), cc_unref(), ast_cc_monitor::core_id, generic_monitor_instance::core_id, ast_cc_interface::device_name, find_generic_monitor_instance_list(), ast_cc_monitor::interface, generic_monitor_instance::is_suspended, and generic_monitor_instance_list::list.
01313 { 01314 struct generic_monitor_instance_list *generic_list; 01315 struct generic_monitor_instance *generic_instance; 01316 enum ast_device_state state = ast_device_state(monitor->interface->device_name); 01317 01318 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) { 01319 return -1; 01320 } 01321 01322 /* First we need to mark this particular monitor as being suspended. */ 01323 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01324 if (generic_instance->core_id == monitor->core_id) { 01325 generic_instance->is_suspended = 1; 01326 break; 01327 } 01328 } 01329 01330 /* If the device being suspended is currently in use, then we don't need to 01331 * take any further actions 01332 */ 01333 if (!cc_generic_is_device_available(state)) { 01334 cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list."); 01335 return 0; 01336 } 01337 01338 /* If the device is not in use, though, then it may be possible to report the 01339 * device's availability using a different monitor which is monitoring the 01340 * same device 01341 */ 01342 01343 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01344 if (!generic_instance->is_suspended) { 01345 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available"); 01346 break; 01347 } 01348 } 01349 cc_unref(generic_list, "Done with generic list in suspend callback"); 01350 return 0; 01351 }
static int cc_generic_monitor_unsuspend | ( | struct ast_cc_monitor * | monitor | ) | [static] |
Definition at line 1353 of file ccss.c.
References ast_cc_monitor_callee_available(), AST_LIST_TRAVERSE, cc_generic_is_device_available(), cc_unref(), generic_monitor_instance::core_id, ast_cc_monitor::core_id, ast_cc_interface::device_name, find_generic_monitor_instance_list(), ast_cc_monitor::interface, generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, and generic_monitor_instance::monitoring.
01354 { 01355 struct generic_monitor_instance *generic_instance; 01356 struct generic_monitor_instance_list *generic_list = find_generic_monitor_instance_list(monitor->interface->device_name); 01357 enum ast_device_state state = ast_device_state(monitor->interface->device_name); 01358 01359 if (!generic_list) { 01360 return -1; 01361 } 01362 /* If the device is currently available, we can immediately announce 01363 * its availability 01364 */ 01365 if (cc_generic_is_device_available(state)) { 01366 ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available"); 01367 } 01368 01369 /* In addition, we need to mark this generic_monitor_instance as not being suspended anymore */ 01370 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01371 if (generic_instance->core_id == monitor->core_id) { 01372 generic_instance->is_suspended = 0; 01373 generic_instance->monitoring = 1; 01374 break; 01375 } 01376 } 01377 cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend"); 01378 return 0; 01379 }
static void cc_interface_destroy | ( | void * | data | ) | [static] |
Definition at line 1467 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().
01468 { 01469 struct ast_cc_interface *interface = data; 01470 ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name); 01471 ast_cc_config_params_destroy(interface->config_params); 01472 }
static void cc_interface_tree_destroy | ( | void * | data | ) | [static] |
Definition at line 1588 of file ccss.c.
References AST_LIST_HEAD_DESTROY, AST_LIST_REMOVE_HEAD, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_unref(), and monitor.
Referenced by cc_interfaces_datastore_init().
01589 { 01590 struct cc_monitor_tree *cc_interface_tree = data; 01591 struct ast_cc_monitor *monitor; 01592 while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) { 01593 if (monitor->callbacks) { 01594 monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id); 01595 } 01596 cc_unref(monitor, "Destroying all monitors"); 01597 } 01598 AST_LIST_HEAD_DESTROY(cc_interface_tree); 01599 }
static int cc_interfaces_datastore_init | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 1868 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_cc_monitor::core_id, dialed_cc_interfaces::core_id, ast_datastore::data, DATASTORE_INHERIT_FOREVER, dialed_cc_interfaces::dial_parent_id, ast_channel::exten, ast_cc_monitor::id, ast_datastore::inheritance, dialed_cc_interfaces::interface_tree, dialed_cc_interfaces::is_original_caller, ast_channel::macrocontext, ast_channel::macroexten, monitor, and S_OR.
Referenced by ast_cc_call_init().
01868 { 01869 struct dialed_cc_interfaces *interfaces; 01870 struct ast_cc_monitor *monitor; 01871 struct ast_datastore *dial_cc_datastore; 01872 01873 /*XXX This may be a bit controversial. In an attempt to not allocate 01874 * extra resources, I make sure that a future request will be within 01875 * limits. The problem here is that it is reasonable to think that 01876 * even if we're not within the limits at this point, we may be by 01877 * the time the requestor will have made his request. This may be 01878 * deleted at some point. 01879 */ 01880 if (!ast_cc_request_is_within_limits()) { 01881 return 0; 01882 } 01883 01884 if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) { 01885 return -1; 01886 } 01887 01888 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten), S_OR(chan->macrocontext, chan->context), 0))) { 01889 ast_free(interfaces); 01890 return -1; 01891 } 01892 01893 if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) { 01894 cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor"); 01895 ast_free(interfaces); 01896 return -1; 01897 } 01898 01899 if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy, 01900 "Allocate monitor tree"))) { 01901 ast_datastore_free(dial_cc_datastore); 01902 cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor"); 01903 ast_free(interfaces); 01904 return -1; 01905 } 01906 01907 /* Finally, all that allocation is done... */ 01908 AST_LIST_HEAD_INIT(interfaces->interface_tree); 01909 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next); 01910 cc_ref(monitor, "List's reference to extension monitor"); 01911 dial_cc_datastore->data = interfaces; 01912 dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER; 01913 interfaces->dial_parent_id = monitor->id; 01914 interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1); 01915 interfaces->is_original_caller = 1; 01916 ast_channel_lock(chan); 01917 ast_channel_datastore_add(chan, dial_cc_datastore); 01918 ast_channel_unlock(chan); 01919 cc_unref(monitor, "Unreffing allocation's reference"); 01920 return 0; 01921 }
static void cc_monitor_destroy | ( | void * | data | ) | [static] |
Definition at line 1567 of file ccss.c.
References AST_CC_EXTENSION_MONITOR, ast_free, ast_log_dynamic_level, ast_cc_monitor::callbacks, cc_extension_monitor_destructor(), cc_unref(), ast_cc_monitor::core_id, ast_cc_monitor_callbacks::destructor, ast_cc_interface::device_name, ast_cc_monitor::dialstring, ast_cc_monitor::interface, monitor, ast_cc_interface::monitor_class, and ast_cc_monitor::private_data.
Referenced by cc_device_monitor_init(), and cc_extension_monitor_init().
01568 { 01569 struct ast_cc_monitor *monitor = data; 01570 /* During the monitor creation process, it is possible for this 01571 * function to be called prior to when callbacks are assigned 01572 * to the monitor. Also, extension monitors do not have callbacks 01573 * assigned to them, so we wouldn't want to segfault when we try 01574 * to destroy one of them. 01575 */ 01576 ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n", 01577 monitor->core_id, monitor->interface->device_name); 01578 if (monitor->interface->monitor_class == AST_CC_EXTENSION_MONITOR) { 01579 cc_extension_monitor_destructor(monitor->private_data); 01580 } 01581 if (monitor->callbacks) { 01582 monitor->callbacks->destructor(monitor->private_data); 01583 } 01584 cc_unref(monitor->interface, "Unreffing tree's reference to interface"); 01585 ast_free(monitor->dialstring); 01586 }
static int cc_monitor_failed | ( | void * | data | ) | [static] |
Definition at line 3630 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, and ast_cc_monitor::parent_id.
Referenced by ast_cc_monitor_failed().
03631 { 03632 struct ast_cc_monitor_failure_data *failure_data = data; 03633 struct cc_core_instance *core_instance; 03634 struct ast_cc_monitor *monitor_iter; 03635 03636 core_instance = find_cc_core_instance(failure_data->core_id); 03637 if (!core_instance) { 03638 /* Core instance no longer exists or invalid core_id. */ 03639 ast_log_dynamic_level(cc_logger_level, 03640 "Core %d: Could not find core instance for device %s '%s'\n", 03641 failure_data->core_id, failure_data->device_name, failure_data->debug); 03642 ast_free((char *) failure_data->device_name); 03643 ast_free((char *) failure_data->debug); 03644 ast_free(failure_data); 03645 return -1; 03646 } 03647 03648 AST_LIST_LOCK(core_instance->monitors); 03649 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 03650 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 03651 if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) { 03652 AST_LIST_REMOVE_CURRENT(next); 03653 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 03654 monitor_iter->interface->device_name, 1); 03655 monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id); 03656 manager_event(EVENT_FLAG_CC, "CCMonitorFailed", 03657 "CoreID: %d\r\n" 03658 "Callee: %s\r\n", 03659 monitor_iter->core_id, monitor_iter->interface->device_name); 03660 cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference."); 03661 } 03662 } 03663 } 03664 AST_LIST_TRAVERSE_SAFE_END; 03665 03666 if (!has_device_monitors(core_instance)) { 03667 ast_cc_failed(core_instance->core_id, "All monitors have failed\n"); 03668 } 03669 AST_LIST_UNLOCK(core_instance->monitors); 03670 cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n"); 03671 03672 ast_free((char *) failure_data->device_name); 03673 ast_free((char *) failure_data->debug); 03674 ast_free(failure_data); 03675 return 0; 03676 }
static int cc_offer | ( | const int | core_id, | |
const char *const | debug, | |||
... | ||||
) | [static] |
Definition at line 3474 of file ccss.c.
References CC_CALLER_OFFERED, and cc_request_state_change().
Referenced by ast_cc_offer().
03475 { 03476 va_list ap; 03477 int res; 03478 03479 va_start(ap, debug); 03480 res = cc_request_state_change(CC_CALLER_OFFERED, core_id, debug, ap); 03481 va_end(ap); 03482 return res; 03483 }
static int cc_party_b_free | ( | void * | data | ) | [static] |
Definition at line 3776 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().
03777 { 03778 struct cc_core_instance *core_instance = data; 03779 int res = 0; 03780 03781 if (core_instance->agent->callbacks->party_b_free) { 03782 res = core_instance->agent->callbacks->party_b_free(core_instance->agent); 03783 } 03784 cc_unref(core_instance, "Party B free finished. Unref core_instance"); 03785 return res; 03786 }
static void cc_recall_ds_destroy | ( | void * | data | ) | [static] |
Definition at line 3126 of file ccss.c.
References ast_free, cc_unref(), and cc_recall_ds_data::interface_tree.
03127 { 03128 struct cc_recall_ds_data *recall_data = data; 03129 recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree"); 03130 ast_free(recall_data); 03131 }
static void* cc_recall_ds_duplicate | ( | void * | data | ) | [static] |
Definition at line 3112 of file ccss.c.
References ast_calloc, cc_ref(), cc_recall_ds_data::core_id, cc_recall_ds_data::interface_tree, and cc_recall_ds_data::nested.
03113 { 03114 struct cc_recall_ds_data *old_data = data; 03115 struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data)); 03116 03117 if (!new_data) { 03118 return NULL; 03119 } 03120 new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate"); 03121 new_data->core_id = old_data->core_id; 03122 new_data->nested = 1; 03123 return new_data; 03124 }
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 2977 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.
02978 { 02979 /* Both caller and callee are available, call agent's recall callback 02980 */ 02981 cancel_available_timer(core_instance); 02982 manager_event(EVENT_FLAG_CC, "CCCallerRecalling", 02983 "CoreID: %d\r\n" 02984 "Caller: %s\r\n", 02985 core_instance->core_id, core_instance->agent->device_name); 02986 return 0; 02987 }
static void* cc_ref | ( | void * | obj, | |
const char * | debug | |||
) | [inline, static] |
Definition at line 134 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().
00135 { 00136 ao2_t_ref(obj, +1, debug); 00137 return obj; 00138 }
static int cc_request_state_change | ( | enum cc_state | state, | |
const int | core_id, | |||
const char * | debug, | |||
va_list | ap | |||
) | [static] |
Definition at line 3062 of file ccss.c.
References args, ast_calloc, ast_free, ast_log_dynamic_level, ast_taskprocessor_push(), cc_do_state_change(), cc_unref(), cc_state_change_args::core_id, cc_state_change_args::core_instance, cc_state_change_args::debug, dummy(), find_cc_core_instance(), and cc_state_change_args::state.
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().
03063 { 03064 int res; 03065 int debuglen; 03066 char dummy[1]; 03067 va_list aq; 03068 struct cc_core_instance *core_instance; 03069 struct cc_state_change_args *args; 03070 /* This initial call to vsnprintf is simply to find what the 03071 * size of the string needs to be 03072 */ 03073 va_copy(aq, ap); 03074 /* We add 1 to the result since vsnprintf's return does not 03075 * include the terminating null byte 03076 */ 03077 debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1; 03078 va_end(aq); 03079 03080 if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) { 03081 return -1; 03082 } 03083 03084 core_instance = find_cc_core_instance(core_id); 03085 if (!core_instance) { 03086 ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n", 03087 core_id); 03088 ast_free(args); 03089 return -1; 03090 } 03091 03092 args->core_instance = core_instance; 03093 args->state = state; 03094 args->core_id = core_id; 03095 vsnprintf(args->debug, debuglen, debug, ap); 03096 03097 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_do_state_change, args); 03098 if (res) { 03099 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03100 ast_free(args); 03101 } 03102 return res; 03103 }
static const char* cc_service_to_string | ( | enum ast_cc_service_type | service | ) | [static] |
Definition at line 402 of file ccss.c.
References cc_service_to_string_map.
Referenced by ast_handle_cc_control_frame(), and cc_cli_print_monitor_stats().
00403 { 00404 return cc_service_to_string_map[service].service_string; 00405 }
static void cc_shutdown | ( | void | ) | [static] |
Definition at line 4313 of file ccss.c.
References ao2_t_ref, ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_cli_unregister_multiple(), ast_devstate_prov_del(), ast_logger_unregister_level(), ast_sched_thread_destroy(), ast_taskprocessor_unreference(), ast_unregister_application(), generic_monitor_cbs, and generic_monitors.
Referenced by ast_cc_init().
04314 { 04315 ast_devstate_prov_del("ccss"); 04316 ast_cc_agent_unregister(&generic_agent_callbacks); 04317 ast_cc_monitor_unregister(&generic_monitor_cbs); 04318 ast_unregister_application(cccancel_app); 04319 ast_unregister_application(ccreq_app); 04320 ast_logger_unregister_level(CC_LOGGER_LEVEL_NAME); 04321 ast_cli_unregister_multiple(cc_cli, ARRAY_LEN(cc_cli)); 04322 04323 if (cc_sched_thread) { 04324 cc_sched_thread = ast_sched_thread_destroy(cc_sched_thread); 04325 } 04326 if (cc_core_taskprocessor) { 04327 cc_core_taskprocessor = ast_taskprocessor_unreference(cc_core_taskprocessor); 04328 } 04329 /* Note that cc_core_instances must be disposed of prior to generic_monitors */ 04330 if (cc_core_instances) { 04331 ao2_t_ref(cc_core_instances, -1, "Unref cc_core_instances container in cc_shutdown"); 04332 cc_core_instances = NULL; 04333 } 04334 if (generic_monitors) { 04335 ao2_t_ref(generic_monitors, -1, "Unref generic_monitor container in cc_shutdown"); 04336 generic_monitors = NULL; 04337 } 04338 }
static const char* cc_state_to_string | ( | enum cc_state | state | ) | [static] |
Definition at line 397 of file ccss.c.
References cc_state_to_string_map.
Referenced by cc_do_state_change(), and print_stats_cb().
00398 { 00399 return cc_state_to_string_map[state].state_string; 00400 }
static int cc_status_request | ( | void * | data | ) | [static] |
Definition at line 3713 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().
03714 { 03715 struct cc_core_instance *core_instance= data; 03716 int res; 03717 03718 res = core_instance->agent->callbacks->status_request(core_instance->agent); 03719 cc_unref(core_instance, "Status request finished. Unref core instance"); 03720 return res; 03721 }
static int cc_status_response | ( | void * | data | ) | [static] |
Definition at line 3809 of file ccss.c.
References args, AST_CC_DEVICE_MONITOR, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_unref(), cc_status_response_args::core_instance, cc_status_response_args::devstate, ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, and ast_cc_monitor_callbacks::status_response.
Referenced by ast_cc_agent_status_response().
03810 { 03811 struct cc_status_response_args *args = data; 03812 struct cc_core_instance *core_instance = args->core_instance; 03813 struct ast_cc_monitor *monitor_iter; 03814 enum ast_device_state devstate = args->devstate; 03815 03816 ast_free(args); 03817 03818 AST_LIST_LOCK(core_instance->monitors); 03819 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 03820 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR && 03821 monitor_iter->callbacks->status_response) { 03822 monitor_iter->callbacks->status_response(monitor_iter, devstate); 03823 } 03824 } 03825 AST_LIST_UNLOCK(core_instance->monitors); 03826 cc_unref(core_instance, "Status response finished. Unref core instance"); 03827 return 0; 03828 }
static int cc_stop_ringing | ( | void * | data | ) | [static] |
Definition at line 3739 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().
03740 { 03741 struct cc_core_instance *core_instance = data; 03742 int res = 0; 03743 03744 if (core_instance->agent->callbacks->stop_ringing) { 03745 res = core_instance->agent->callbacks->stop_ringing(core_instance->agent); 03746 } 03747 /* If an agent is being asked to stop ringing, then he needs to be prepared if for 03748 * whatever reason he needs to be called back again. The proper state to be in to 03749 * detect such a circumstance is the CC_ACTIVE state. 03750 * 03751 * We get to this state using the slightly unintuitive method of calling 03752 * ast_cc_monitor_request_acked because it gets us to the proper state. 03753 */ 03754 ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.", 03755 core_instance->agent->device_name); 03756 cc_unref(core_instance, "Stop ringing finished. Unref core_instance"); 03757 return res; 03758 }
static void cc_unique_append | ( | struct ast_str ** | str, | |
const char * | dialstring | |||
) | [static] |
Definition at line 3292 of file ccss.c.
References AST_CHANNEL_NAME, ast_str_append(), ast_str_buffer(), and ast_strlen_zero().
Referenced by build_cc_interfaces_chanvar().
03293 { 03294 char dialstring_search[AST_CHANNEL_NAME]; 03295 03296 if (ast_strlen_zero(dialstring)) { 03297 /* No dialstring to append. */ 03298 return; 03299 } 03300 snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&'); 03301 if (strstr(ast_str_buffer(*str), dialstring_search)) { 03302 return; 03303 } 03304 ast_str_append(str, 0, "%s", dialstring_search); 03305 }
static void* cc_unref | ( | void * | obj, | |
const char * | debug | |||
) | [inline, static] |
Definition at line 140 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().
00141 { 00142 ao2_t_ref(obj, -1, debug); 00143 return NULL; 00144 }
static int cccancel_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 4045 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_log_dynamic_level, ast_cc_agent::callbacks, cc_unref(), cc_core_instance::core_id, LOG_WARNING, match_agent(), MATCH_REQUEST, pbx_builtin_setvar_helper(), and ast_cc_agent_callbacks::type.
Referenced by ast_cc_init().
04046 { 04047 struct cc_core_instance *core_instance; 04048 char device_name[AST_CHANNEL_NAME]; 04049 unsigned long match_flags; 04050 int res; 04051 04052 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 04053 04054 match_flags = MATCH_REQUEST; 04055 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) { 04056 ast_log_dynamic_level(cc_logger_level, "Cannot find CC transaction to cancel for caller %s\n", device_name); 04057 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL"); 04058 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NO_CORE_INSTANCE"); 04059 return 0; 04060 } 04061 04062 if (strcmp(core_instance->agent->callbacks->type, "generic")) { 04063 ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calles with a generic agent\n"); 04064 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel"); 04065 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL"); 04066 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NOT_GENERIC"); 04067 return 0; 04068 } 04069 res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s", 04070 core_instance->core_id, device_name); 04071 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel"); 04072 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", res ? "FAIL" : "SUCCESS"); 04073 if (res) { 04074 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "UNSPECIFIED"); 04075 } 04076 return 0; 04077 }
static int ccreq_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 3994 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_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().
03995 { 03996 struct cc_core_instance *core_instance; 03997 char device_name[AST_CHANNEL_NAME]; 03998 unsigned long match_flags; 03999 int res; 04000 04001 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 04002 04003 match_flags = MATCH_NO_REQUEST; 04004 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) { 04005 ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name); 04006 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL"); 04007 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NO_CORE_INSTANCE"); 04008 return 0; 04009 } 04010 04011 ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n", 04012 core_instance->core_id, device_name); 04013 04014 if (strcmp(core_instance->agent->callbacks->type, "generic")) { 04015 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n", 04016 core_instance->core_id); 04017 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL"); 04018 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NOT_GENERIC"); 04019 cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent"); 04020 return 0; 04021 } 04022 04023 if (!ast_cc_request_is_within_limits()) { 04024 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n", 04025 core_instance->core_id); 04026 ast_cc_failed(core_instance->core_id, "Too many CC requests\n"); 04027 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL"); 04028 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "TOO_MANY_REQUESTS"); 04029 cc_unref(core_instance, "Unref core_instance since too many CC requests"); 04030 return 0; 04031 } 04032 04033 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); 04034 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS"); 04035 if (res) { 04036 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "UNSPECIFIED"); 04037 } 04038 04039 cc_unref(core_instance, "Done with CallCompletionRequest"); 04040 return 0; 04041 }
static void check_callback_sanity | ( | const struct ast_cc_agent_callbacks * | callbacks | ) | [static] |
Definition at line 2269 of file ccss.c.
References ast_assert, ast_cc_agent_callbacks::callee_available, ast_cc_agent_callbacks::destructor, ast_cc_agent_callbacks::init, ast_cc_agent_callbacks::respond, ast_cc_agent_callbacks::start_monitoring, ast_cc_agent_callbacks::start_offer_timer, ast_cc_agent_callbacks::status_request, and ast_cc_agent_callbacks::stop_offer_timer.
Referenced by cc_agent_init().
02270 { 02271 ast_assert(callbacks->init != NULL); 02272 ast_assert(callbacks->start_offer_timer != NULL); 02273 ast_assert(callbacks->stop_offer_timer != NULL); 02274 ast_assert(callbacks->respond != NULL); 02275 ast_assert(callbacks->status_request != NULL); 02276 ast_assert(callbacks->start_monitoring != NULL); 02277 ast_assert(callbacks->callee_available != NULL); 02278 ast_assert(callbacks->destructor != NULL); 02279 }
static char* complete_core_id | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 4239 of file ccss.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, cc_unref(), and cc_core_instance::core_id.
Referenced by handle_cc_kill().
04240 { 04241 int which = 0; 04242 int wordlen = strlen(word); 04243 char *ret = NULL; 04244 struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0); 04245 struct cc_core_instance *core_instance; 04246 04247 for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance")); 04248 cc_unref(core_instance, "CLI tab completion iteration")) { 04249 char core_id_str[20]; 04250 snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id); 04251 if (!strncmp(word, core_id_str, wordlen) && ++which > state) { 04252 ret = ast_strdup(core_id_str); 04253 cc_unref(core_instance, "Found a matching core ID for CLI tab-completion"); 04254 break; 04255 } 04256 } 04257 ao2_iterator_destroy(&core_iter); 04258 04259 return ret; 04260 }
static long count_agents | ( | const char *const | caller, | |
const int | core_id_exception | |||
) | [static] |
Definition at line 2243 of file ccss.c.
References ao2_t_callback_data, ast_log_dynamic_level, 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().
02244 { 02245 struct count_agents_cb_data data = {.core_id_exception = core_id_exception,}; 02246 02247 ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents"); 02248 ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count); 02249 return data.count; 02250 }
static int count_agents_cb | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 520 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().
00521 { 00522 struct cc_core_instance *core_instance = obj; 00523 const char *name = arg; 00524 struct count_agents_cb_data *cb_data = data; 00525 00526 if (cb_data->core_id_exception == core_instance->core_id) { 00527 ast_log_dynamic_level(cc_logger_level, "Found agent with core_id %d but not counting it toward total\n", core_instance->core_id); 00528 return 0; 00529 } 00530 00531 if (core_instance->current_state >= CC_CALLER_REQUESTED && !strcmp(core_instance->agent->device_name, name)) { 00532 cb_data->count++; 00533 } 00534 return 0; 00535 }
static int count_monitors_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4085 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, and cc_core_instance::monitors.
Referenced by ast_cc_monitor_count().
04086 { 04087 struct cc_core_instance *core_instance = obj; 04088 struct count_monitors_cb_data *cb_data = arg; 04089 const char *device_name = cb_data->device_name; 04090 const char *monitor_type = cb_data->monitor_type; 04091 struct ast_cc_monitor *monitor_iter; 04092 04093 AST_LIST_LOCK(core_instance->monitors); 04094 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 04095 if (!strcmp(monitor_iter->interface->device_name, device_name) && 04096 !strcmp(monitor_iter->interface->monitor_type, monitor_type)) { 04097 cb_data->count++; 04098 break; 04099 } 04100 } 04101 AST_LIST_UNLOCK(core_instance->monitors); 04102 return 0; 04103 }
static struct generic_monitor_instance_list* create_new_generic_list | ( | struct ast_cc_monitor * | monitor | ) | [static, read] |
Definition at line 1131 of file ccss.c.
References ao2_t_alloc, ao2_t_link, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_STATE, ast_event_subscribe(), ast_strdup, ast_tech_to_upper(), cc_unref(), generic_monitor_instance_list::current_state, generic_monitor_instance_list::device_name, ast_cc_interface::device_name, generic_monitor_devstate_cb(), generic_monitor_instance_list_destructor(), generic_monitors, ast_cc_monitor::interface, and generic_monitor_instance_list::sub.
Referenced by cc_generic_monitor_request_cc().
01132 { 01133 struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list), 01134 generic_monitor_instance_list_destructor, "allocate generic monitor instance list"); 01135 char * device_name; 01136 01137 if (!generic_list) { 01138 return NULL; 01139 } 01140 01141 if (!(device_name = ast_strdup(monitor->interface->device_name))) { 01142 cc_unref(generic_list, "Failed to strdup the monitor's device name"); 01143 return NULL; 01144 } 01145 ast_tech_to_upper(device_name); 01146 generic_list->device_name = device_name; 01147 01148 if (!(generic_list->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, 01149 generic_monitor_devstate_cb, "Requesting CC", NULL, 01150 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, monitor->interface->device_name, 01151 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_EXISTS, 01152 AST_EVENT_IE_END))) { 01153 cc_unref(generic_list, "Failed to subscribe to device state"); 01154 return NULL; 01155 } 01156 generic_list->current_state = ast_device_state(monitor->interface->device_name); 01157 ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list"); 01158 return generic_list; 01159 }
static void dialed_cc_interfaces_destroy | ( | void * | data | ) | [static] |
Definition at line 1674 of file ccss.c.
References ast_free, cc_unref(), and dialed_cc_interfaces::interface_tree.
01675 { 01676 struct dialed_cc_interfaces *cc_interfaces = data; 01677 cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree"); 01678 ast_free(cc_interfaces); 01679 }
static void* dialed_cc_interfaces_duplicate | ( | void * | data | ) | [static] |
Definition at line 1694 of file ccss.c.
References ast_calloc, cc_ref(), dialed_cc_interfaces::core_id, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, and dialed_cc_interfaces::is_original_caller.
01695 { 01696 struct dialed_cc_interfaces *old_cc_interfaces = data; 01697 struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces)); 01698 if (!new_cc_interfaces) { 01699 return NULL; 01700 } 01701 new_cc_interfaces->ignore = old_cc_interfaces->ignore; 01702 new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id; 01703 new_cc_interfaces->is_original_caller = 0; 01704 cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree"); 01705 new_cc_interfaces->core_id = old_cc_interfaces->core_id; 01706 new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree; 01707 return new_cc_interfaces; 01708 }
static struct extension_monitor_pvt* extension_monitor_pvt_init | ( | void | ) | [static, read] |
Definition at line 1725 of file ccss.c.
References ast_calloc, AST_LIST_HEAD_INIT_NOLOCK, and extension_monitor_pvt::child_dialstrings.
Referenced by cc_extension_monitor_init().
01726 { 01727 struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt)); 01728 if (!ext_pvt) { 01729 return NULL; 01730 } 01731 AST_LIST_HEAD_INIT_NOLOCK(&ext_pvt->child_dialstrings); 01732 return ext_pvt; 01733 }
static struct ast_cc_agent_callbacks* find_agent_callbacks | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 980 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().
00981 { 00982 struct cc_agent_backend *backend; 00983 const struct ast_cc_agent_callbacks *callbacks = NULL; 00984 struct ast_cc_config_params *cc_params; 00985 char type[32]; 00986 00987 cc_params = ast_channel_get_cc_config_params(chan); 00988 if (!cc_params) { 00989 return NULL; 00990 } 00991 switch (ast_get_cc_agent_policy(cc_params)) { 00992 case AST_CC_AGENT_GENERIC: 00993 ast_copy_string(type, "generic", sizeof(type)); 00994 break; 00995 case AST_CC_AGENT_NATIVE: 00996 ast_channel_get_cc_agent_type(chan, type, sizeof(type)); 00997 break; 00998 default: 00999 ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n"); 01000 return NULL; 01001 } 01002 01003 AST_RWLIST_RDLOCK(&cc_agent_backends); 01004 AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) { 01005 if (!strcmp(backend->callbacks->type, type)) { 01006 ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type); 01007 callbacks = backend->callbacks; 01008 break; 01009 } 01010 } 01011 AST_RWLIST_UNLOCK(&cc_agent_backends); 01012 return callbacks; 01013 }
static struct cc_core_instance* find_cc_core_instance | ( | const int | core_id | ) | [static, read] |
Definition at line 421 of file ccss.c.
References ao2_t_find, 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().
00422 { 00423 struct cc_core_instance finder = {.core_id = core_id,}; 00424 00425 return ao2_t_find(cc_core_instances, &finder, OBJ_POINTER, "Finding a core_instance"); 00426 }
static struct generic_monitor_instance_list* find_generic_monitor_instance_list | ( | const char *const | device_name | ) | [static, read] |
Definition at line 1108 of file ccss.c.
References ao2_t_find, ast_strdupa, ast_tech_to_upper(), 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().
01109 { 01110 struct generic_monitor_instance_list finder = {0}; 01111 char *uppertech = ast_strdupa(device_name); 01112 ast_tech_to_upper(uppertech); 01113 finder.device_name = uppertech; 01114 01115 return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list"); 01116 }
static struct ast_cc_monitor_callbacks* find_monitor_callbacks | ( | const char *const | type | ) | [static, read] |
Definition at line 911 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().
00912 { 00913 struct cc_monitor_backend *backend; 00914 const struct ast_cc_monitor_callbacks *callbacks = NULL; 00915 00916 AST_RWLIST_RDLOCK(&cc_monitor_backends); 00917 AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) { 00918 if (!strcmp(backend->callbacks->type, type)) { 00919 ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type); 00920 callbacks = backend->callbacks; 00921 break; 00922 } 00923 } 00924 AST_RWLIST_UNLOCK(&cc_monitor_backends); 00925 return callbacks; 00926 }
static void generic_agent_devstate_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 2510 of file ccss.c.
References ast_cc_agent_caller_available(), ast_event_get_ie_uint(), AST_EVENT_IE_STATE, ast_taskprocessor_push(), cc_generic_is_device_available(), 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().
02511 { 02512 struct ast_cc_agent *agent = userdata; 02513 enum ast_device_state new_state; 02514 02515 new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 02516 if (!cc_generic_is_device_available(new_state)) { 02517 /* Not interested in this new state of the device. It is still busy. */ 02518 return; 02519 } 02520 02521 /* We can't unsubscribe from device state events here because it causes a deadlock */ 02522 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_agent_devstate_unsubscribe, 02523 cc_ref(agent, "ref agent for device state unsubscription"))) { 02524 cc_unref(agent, "Unref agent unsubscribing from devstate failed"); 02525 } 02526 ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name); 02527 }
static int generic_agent_devstate_unsubscribe | ( | void * | data | ) | [static] |
Definition at line 2498 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().
02499 { 02500 struct ast_cc_agent *agent = data; 02501 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02502 02503 if (generic_pvt->sub != NULL) { 02504 generic_pvt->sub = ast_event_unsubscribe(generic_pvt->sub); 02505 } 02506 cc_unref(agent, "Done unsubscribing from devstate"); 02507 return 0; 02508 }
static int generic_monitor_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1100 of file ccss.c.
References CMP_MATCH, CMP_STOP, and generic_monitor_instance_list::device_name.
Referenced by ast_cc_init().
01101 { 01102 const struct generic_monitor_instance_list *generic_list1 = obj; 01103 const struct generic_monitor_instance_list *generic_list2 = arg; 01104 01105 return !strcmp(generic_list1->device_name, generic_list2->device_name) ? CMP_MATCH | CMP_STOP : 0; 01106 }
static void generic_monitor_devstate_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 1214 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(), generic_tp_cb_data::device_name, generic_monitor_devstate_tp_cb(), and generic_tp_cb_data::new_state.
Referenced by create_new_generic_list().
01215 { 01216 /* Wow, it's cool that we've picked up on a state change, but we really want 01217 * the actual work to be done in the core's taskprocessor execution thread 01218 * so that all monitor operations can be serialized. Locks?! We don't need 01219 * no steenkin' locks! 01220 */ 01221 struct generic_tp_cb_data *gtcd = ast_calloc(1, sizeof(*gtcd)); 01222 01223 if (!gtcd) { 01224 return; 01225 } 01226 01227 if (!(gtcd->device_name = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE)))) { 01228 ast_free(gtcd); 01229 return; 01230 } 01231 gtcd->new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 01232 01233 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_monitor_devstate_tp_cb, gtcd)) { 01234 ast_free((char *)gtcd->device_name); 01235 ast_free(gtcd); 01236 } 01237 }
static int generic_monitor_devstate_tp_cb | ( | void * | data | ) | [static] |
Definition at line 1166 of file ccss.c.
References ast_cc_monitor_callee_available(), AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_UNAVAILABLE, ast_free, AST_LIST_TRAVERSE, cc_generic_is_device_available(), 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, and generic_tp_cb_data::new_state.
Referenced by generic_monitor_devstate_cb().
01167 { 01168 struct generic_tp_cb_data *gtcd = data; 01169 enum ast_device_state new_state = gtcd->new_state; 01170 enum ast_device_state previous_state = gtcd->new_state; 01171 const char *monitor_name = gtcd->device_name; 01172 struct generic_monitor_instance_list *generic_list; 01173 struct generic_monitor_instance *generic_instance; 01174 01175 if (!(generic_list = find_generic_monitor_instance_list(monitor_name))) { 01176 /* The most likely cause for this is that we destroyed the monitor in the 01177 * time between subscribing to its device state and the time this executes. 01178 * Not really a big deal. 01179 */ 01180 ast_free((char *) gtcd->device_name); 01181 ast_free(gtcd); 01182 return 0; 01183 } 01184 01185 if (generic_list->current_state == new_state) { 01186 /* The device state hasn't actually changed, so we don't really care */ 01187 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback"); 01188 ast_free((char *) gtcd->device_name); 01189 ast_free(gtcd); 01190 return 0; 01191 } 01192 01193 previous_state = generic_list->current_state; 01194 generic_list->current_state = new_state; 01195 01196 if (cc_generic_is_device_available(new_state) && 01197 (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE || 01198 previous_state == AST_DEVICE_BUSY)) { 01199 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01200 if (!generic_instance->is_suspended && generic_instance->monitoring) { 01201 generic_instance->monitoring = 0; 01202 generic_list->fit_for_recall = 1; 01203 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available"); 01204 break; 01205 } 01206 } 01207 } 01208 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback"); 01209 ast_free((char *) gtcd->device_name); 01210 ast_free(gtcd); 01211 return 0; 01212 }
static int generic_monitor_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1094 of file ccss.c.
References ast_str_hash(), and generic_monitor_instance_list::device_name.
Referenced by ast_cc_init().
01095 { 01096 const struct generic_monitor_instance_list *generic_list = obj; 01097 return ast_str_hash(generic_list->device_name); 01098 }
static void generic_monitor_instance_list_destructor | ( | void * | obj | ) | [static] |
Definition at line 1118 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, and generic_monitor_instance_list::sub.
Referenced by create_new_generic_list().
01119 { 01120 struct generic_monitor_instance_list *generic_list = obj; 01121 struct generic_monitor_instance *generic_instance; 01122 01123 generic_list->sub = ast_event_unsubscribe(generic_list->sub); 01124 while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) { 01125 ast_free(generic_instance); 01126 } 01127 ast_free((char *)generic_list->device_name); 01128 }
static void* generic_recall | ( | void * | data | ) | [static] |
Definition at line 2548 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().
02549 { 02550 struct ast_cc_agent *agent = data; 02551 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02552 const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name)); 02553 const char *tech; 02554 char *target; 02555 int reason; 02556 struct ast_channel *chan; 02557 const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params); 02558 unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000; 02559 02560 tech = interface; 02561 if ((target = strchr(interface, '/'))) { 02562 *target++ = '\0'; 02563 } 02564 if (!(chan = ast_request_and_dial(tech, AST_FORMAT_SLINEAR, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) { 02565 /* Hmm, no channel. Sucks for you, bud. 02566 */ 02567 ast_log_dynamic_level(cc_logger_level, "Core %d: Failed to call back %s for reason %d\n", 02568 agent->core_id, agent->device_name, reason); 02569 ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target); 02570 return NULL; 02571 } 02572 02573 /* We have a channel. It's time now to set up the datastore of recalled CC interfaces. 02574 * This will be a common task for all recall functions. If it were possible, I'd have 02575 * the core do it automatically, but alas I cannot. Instead, I will provide a public 02576 * function to do so. 02577 */ 02578 ast_setup_cc_recall_datastore(chan, agent->core_id); 02579 ast_cc_agent_set_interfaces_chanvar(chan); 02580 02581 ast_copy_string(chan->exten, generic_pvt->exten, sizeof(chan->exten)); 02582 ast_copy_string(chan->context, generic_pvt->context, sizeof(chan->context)); 02583 chan->priority = 1; 02584 02585 pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten); 02586 pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context); 02587 02588 if (!ast_strlen_zero(callback_macro)) { 02589 ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback macro configured for agent %s\n", 02590 agent->core_id, agent->device_name); 02591 if (ast_app_run_macro(NULL, chan, callback_macro, NULL)) { 02592 ast_cc_failed(agent->core_id, "Callback macro to %s failed. Maybe a hangup?", agent->device_name); 02593 ast_hangup(chan); 02594 return NULL; 02595 } 02596 } 02597 if (ast_pbx_start(chan)) { 02598 ast_cc_failed(agent->core_id, "PBX failed to start for %s.", agent->device_name); 02599 ast_hangup(chan); 02600 return NULL; 02601 } 02602 ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling", 02603 agent->device_name); 02604 return NULL; 02605 }
static char* handle_cc_kill | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4262 of file ccss.c.
References ao2_t_callback, ast_cli_args::argc, ast_cli_args::argv, ast_cli_complete(), 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.
04263 { 04264 static const char * const option[] = { "core", "all", NULL }; 04265 04266 switch (cmd) { 04267 case CLI_INIT: 04268 e->command = "cc cancel"; 04269 e->usage = 04270 "Usage: cc cancel can be used in two ways.\n" 04271 " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n" 04272 " core ID equal to the specified core ID.\n" 04273 " 2. 'cc cancel all' will cancel all active CC transactions.\n"; 04274 return NULL; 04275 case CLI_GENERATE: 04276 if (a->pos == 2) { 04277 return ast_cli_complete(a->word, option, a->n); 04278 } 04279 if (a->pos == 3) { 04280 return complete_core_id(a->line, a->word, a->pos, a->n); 04281 } 04282 return NULL; 04283 } 04284 04285 if (a->argc == 4) { 04286 int core_id; 04287 char *endptr; 04288 if (strcasecmp(a->argv[2], "core")) { 04289 return CLI_SHOWUSAGE; 04290 } 04291 core_id = strtol(a->argv[3], &endptr, 10); 04292 if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) { 04293 return CLI_SHOWUSAGE; 04294 } 04295 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id"); 04296 } else if (a->argc == 3) { 04297 if (strcasecmp(a->argv[2], "all")) { 04298 return CLI_SHOWUSAGE; 04299 } 04300 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores"); 04301 } else { 04302 return CLI_SHOWUSAGE; 04303 } 04304 04305 return CLI_SUCCESS; 04306 }
static char* handle_cc_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4195 of file ccss.c.
References ast_cli_args::argc, ast_free, ast_malloc, ast_taskprocessor_push(), cc_cli_output_status(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
04196 { 04197 int *cli_fd; 04198 04199 switch (cmd) { 04200 case CLI_INIT: 04201 e->command = "cc report status"; 04202 e->usage = 04203 "Usage: cc report status\n" 04204 " Report the current status of any ongoing CC transactions\n"; 04205 return NULL; 04206 case CLI_GENERATE: 04207 return NULL; 04208 } 04209 04210 if (a->argc != 3) { 04211 return CLI_SHOWUSAGE; 04212 } 04213 04214 cli_fd = ast_malloc(sizeof(*cli_fd)); 04215 if (!cli_fd) { 04216 return CLI_FAILURE; 04217 } 04218 04219 *cli_fd = a->fd; 04220 04221 if (ast_taskprocessor_push(cc_core_taskprocessor, cc_cli_output_status, cli_fd)) { 04222 ast_free(cli_fd); 04223 return CLI_FAILURE; 04224 } 04225 return CLI_SUCCESS; 04226 }
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 2809 of file ccss.c.
References AST_CC_DEVICE_MONITOR, AST_LIST_TRAVERSE, ast_cc_monitor::interface, ast_cc_interface::monitor_class, and cc_core_instance::monitors.
Referenced by cancel_available_timer(), cc_monitor_failed(), request_cc(), suspend(), and unsuspend().
02810 { 02811 struct ast_cc_monitor *iter; 02812 int res = 0; 02813 02814 AST_LIST_TRAVERSE(core_instance->monitors, iter, next) { 02815 if (iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02816 res = 1; 02817 break; 02818 } 02819 } 02820 02821 return res; 02822 }
static void initialize_cc_max_requests | ( | void | ) | [static] |
Definition at line 4114 of file ccss.c.
References ast_config_destroy(), ast_config_load2(), ast_log(), ast_strlen_zero(), ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, GLOBAL_CC_MAX_REQUESTS_DEFAULT, and LOG_WARNING.
Referenced by ast_cc_init().
04115 { 04116 struct ast_config *cc_config; 04117 const char *cc_max_requests_str; 04118 struct ast_flags config_flags = {0,}; 04119 char *endptr; 04120 04121 cc_config = ast_config_load2("ccss.conf", "ccss", config_flags); 04122 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) { 04123 ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests default\n"); 04124 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT; 04125 return; 04126 } 04127 04128 if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) { 04129 ast_config_destroy(cc_config); 04130 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT; 04131 return; 04132 } 04133 04134 global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10); 04135 04136 if (!ast_strlen_zero(endptr)) { 04137 ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n"); 04138 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT; 04139 } 04140 04141 ast_config_destroy(cc_config); 04142 return; 04143 }
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 2713 of file ccss.c.
References 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().
02714 { 02715 int is_valid = 0; 02716 switch (new_state) { 02717 case CC_AVAILABLE: 02718 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to state %d? That should never happen.\n", 02719 agent->core_id, new_state); 02720 break; 02721 case CC_CALLER_OFFERED: 02722 if (current_state == CC_AVAILABLE) { 02723 is_valid = 1; 02724 } 02725 break; 02726 case CC_CALLER_REQUESTED: 02727 if (current_state == CC_CALLER_OFFERED || 02728 (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) { 02729 is_valid = 1; 02730 } 02731 break; 02732 case CC_ACTIVE: 02733 if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) { 02734 is_valid = 1; 02735 } 02736 break; 02737 case CC_CALLEE_READY: 02738 if (current_state == CC_ACTIVE) { 02739 is_valid = 1; 02740 } 02741 break; 02742 case CC_CALLER_BUSY: 02743 if (current_state == CC_CALLEE_READY) { 02744 is_valid = 1; 02745 } 02746 break; 02747 case CC_RECALLING: 02748 if (current_state == CC_CALLEE_READY) { 02749 is_valid = 1; 02750 } 02751 break; 02752 case CC_COMPLETE: 02753 if (current_state == CC_RECALLING) { 02754 is_valid = 1; 02755 } 02756 break; 02757 case CC_FAILED: 02758 is_valid = 1; 02759 break; 02760 default: 02761 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to unknown state %d\n", 02762 agent->core_id, new_state); 02763 break; 02764 } 02765 02766 return is_valid; 02767 }
static int kill_cores | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4228 of file ccss.c.
References ast_cc_failed(), and cc_core_instance::core_id.
Referenced by handle_cc_kill().
04229 { 04230 int *core_id = arg; 04231 struct cc_core_instance *core_instance = obj; 04232 04233 if (!core_id || (core_instance->core_id == *core_id)) { 04234 ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n"); 04235 } 04236 return 0; 04237 }
static void kill_duplicate_offers | ( | char * | caller | ) | [static] |
Definition at line 2252 of file ccss.c.
References ao2_iterator_destroy(), ao2_t_callback_data, match_agent(), MATCH_NO_REQUEST, OBJ_MULTIPLE, and OBJ_UNLINK.
Referenced by cc_core_init_instance().
02253 { 02254 unsigned long match_flags = MATCH_NO_REQUEST; 02255 struct ao2_iterator *dups_iter; 02256 02257 /* 02258 * Must remove the ref that was in cc_core_instances outside of 02259 * the container lock to prevent deadlock. 02260 */ 02261 dups_iter = ao2_t_callback_data(cc_core_instances, OBJ_MULTIPLE | OBJ_UNLINK, 02262 match_agent, caller, &match_flags, "Killing duplicate offers"); 02263 if (dups_iter) { 02264 /* Now actually unref any duplicate offers by simply destroying the iterator. */ 02265 ao2_iterator_destroy(dups_iter); 02266 } 02267 }
static int match_agent | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 482 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().
00483 { 00484 struct cc_core_instance *core_instance = obj; 00485 const char *name = arg; 00486 unsigned long match_flags = *(unsigned long *)data; 00487 int possible_match = 0; 00488 00489 if ((match_flags & MATCH_NO_REQUEST) && core_instance->current_state < CC_CALLER_REQUESTED) { 00490 possible_match = 1; 00491 } 00492 00493 if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) { 00494 possible_match = 1; 00495 } 00496 00497 if (!possible_match) { 00498 return 0; 00499 } 00500 00501 if (!strcmp(core_instance->agent->device_name, name)) { 00502 return CMP_MATCH | CMP_STOP; 00503 } 00504 return 0; 00505 }
static const char* monitor_policy_to_str | ( | enum ast_cc_monitor_policies | policy | ) | [static] |
Definition at line 629 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().
00630 { 00631 switch (policy) { 00632 case AST_CC_MONITOR_NEVER: 00633 return "never"; 00634 case AST_CC_MONITOR_NATIVE: 00635 return "native"; 00636 case AST_CC_MONITOR_GENERIC: 00637 return "generic"; 00638 case AST_CC_MONITOR_ALWAYS: 00639 return "always"; 00640 default: 00641 /* This should never happen... */ 00642 return ""; 00643 } 00644 }
static int offer_timer_expire | ( | const void * | data | ) | [static] |
Definition at line 2428 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().
02429 { 02430 struct ast_cc_agent *agent = (struct ast_cc_agent *) data; 02431 struct cc_generic_agent_pvt *agent_pvt = agent->private_data; 02432 ast_log_dynamic_level(cc_logger_level, "Core %d: Queuing change request because offer timer has expired.\n", 02433 agent->core_id); 02434 agent_pvt->offer_timer_id = -1; 02435 ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name); 02436 cc_unref(agent, "Remove scheduler's reference to the agent"); 02437 return 0; 02438 }
static int print_stats_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4165 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().
04166 { 04167 int *cli_fd = arg; 04168 struct cc_core_instance *core_instance = obj; 04169 04170 ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name, 04171 cc_state_to_string(core_instance->current_state)); 04172 AST_LIST_LOCK(core_instance->monitors); 04173 cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0); 04174 AST_LIST_UNLOCK(core_instance->monitors); 04175 return 0; 04176 }
static void request_cc | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2824 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, ast_cc_interface::device_name, EVENT_FLAG_CC, has_device_monitors(), ast_cc_monitor::interface, manager_event, ast_cc_interface::monitor_class, cc_core_instance::monitors, ast_cc_monitor::parent_id, and ast_cc_monitor_callbacks::request_cc.
Referenced by cc_caller_requested().
02825 { 02826 struct ast_cc_monitor *monitor_iter; 02827 AST_LIST_LOCK(core_instance->monitors); 02828 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02829 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02830 if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) { 02831 AST_LIST_REMOVE_CURRENT(next); 02832 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02833 monitor_iter->interface->device_name, 1); 02834 cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor"); 02835 } else { 02836 manager_event(EVENT_FLAG_CC, "CCRequested", 02837 "CoreID: %d\r\n" 02838 "Caller: %s\r\n" 02839 "Callee: %s\r\n", 02840 core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name); 02841 } 02842 } 02843 } 02844 AST_LIST_TRAVERSE_SAFE_END; 02845 02846 if (!has_device_monitors(core_instance)) { 02847 ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC"); 02848 } 02849 AST_LIST_UNLOCK(core_instance->monitors); 02850 }
static enum ast_cc_agent_policies str_to_agent_policy | ( | const char *const | value | ) | [static] |
Definition at line 584 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().
00585 { 00586 if (!strcasecmp(value, "never")) { 00587 return AST_CC_AGENT_NEVER; 00588 } else if (!strcasecmp(value, "native")) { 00589 return AST_CC_AGENT_NATIVE; 00590 } else if (!strcasecmp(value, "generic")) { 00591 return AST_CC_AGENT_GENERIC; 00592 } else { 00593 ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value); 00594 return AST_CC_AGENT_NEVER; 00595 } 00596 }
static enum ast_cc_monitor_policies str_to_monitor_policy | ( | const char *const | value | ) | [static] |
Definition at line 598 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().
00599 { 00600 if (!strcasecmp(value, "never")) { 00601 return AST_CC_MONITOR_NEVER; 00602 } else if (!strcasecmp(value, "native")) { 00603 return AST_CC_MONITOR_NATIVE; 00604 } else if (!strcasecmp(value, "generic")) { 00605 return AST_CC_MONITOR_GENERIC; 00606 } else if (!strcasecmp(value, "always")) { 00607 return AST_CC_MONITOR_ALWAYS; 00608 } else { 00609 ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value); 00610 return AST_CC_MONITOR_NEVER; 00611 } 00612 }
static void suspend | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2919 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, ast_cc_interface::device_name, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, ast_cc_monitor::parent_id, and ast_cc_monitor_callbacks::suspend.
Referenced by cc_caller_busy(), and handle_controlstreamfile().
02920 { 02921 struct ast_cc_monitor *monitor_iter; 02922 AST_LIST_LOCK(core_instance->monitors); 02923 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02924 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02925 if (monitor_iter->callbacks->suspend(monitor_iter)) { 02926 AST_LIST_REMOVE_CURRENT(next); 02927 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02928 monitor_iter->interface->device_name, 1); 02929 cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor"); 02930 } 02931 } 02932 } 02933 AST_LIST_TRAVERSE_SAFE_END; 02934 02935 if (!has_device_monitors(core_instance)) { 02936 ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC"); 02937 } 02938 AST_LIST_UNLOCK(core_instance->monitors); 02939 }
static void unsuspend | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2866 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, ast_cc_interface::device_name, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, ast_cc_monitor::parent_id, and ast_cc_monitor_callbacks::unsuspend.
Referenced by cc_active().
02867 { 02868 struct ast_cc_monitor *monitor_iter; 02869 AST_LIST_LOCK(core_instance->monitors); 02870 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02871 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02872 if (monitor_iter->callbacks->unsuspend(monitor_iter)) { 02873 AST_LIST_REMOVE_CURRENT(next); 02874 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02875 monitor_iter->interface->device_name, 1); 02876 cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor"); 02877 } 02878 } 02879 } 02880 AST_LIST_TRAVERSE_SAFE_END; 02881 02882 if (!has_device_monitors(core_instance)) { 02883 ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC"); 02884 } 02885 AST_LIST_UNLOCK(core_instance->monitors); 02886 }
struct ast_cli_entry cc_cli[] [static] |
{ AST_CLI_DEFINE(handle_cc_status, "Reports CC stats"), AST_CLI_DEFINE(handle_cc_kill, "Kill a CC transaction"), }
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 [static] |
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] |
{ .type = "Dial CC Interfaces", .duplicate = dialed_cc_interfaces_duplicate, .destroy = dialed_cc_interfaces_destroy, }
struct ast_cc_agent_callbacks generic_agent_callbacks [static] |
struct ast_cc_monitor_callbacks generic_monitor_cbs [static] |
Definition at line 1035 of file ccss.c.
Referenced by ast_cc_init(), and cc_shutdown().
struct ao2_container* generic_monitors |
Definition at line 1044 of file ccss.c.
Referenced by ast_cc_init(), cc_generic_monitor_destructor(), cc_shutdown(), 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] |
{ .type = "cc_recall", .duplicate = cc_recall_ds_duplicate, .destroy = cc_recall_ds_destroy, }
const char* service_string |
int(* const state_change_funcs[])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state) [static] |
Referenced by cc_do_state_change().
const char* state_string |