#include "asterisk.h"
#include "asterisk/astobj2.h"
#include "asterisk/strings.h"
#include "asterisk/ccss.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/event.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
Go to the source code of this file.
Data Structures | |
struct | ast_cc_config_params |
struct | ast_cc_monitor_failure_data |
struct | cc_agent_backend |
struct | cc_agent_backends |
struct | cc_callback_helper |
struct | cc_control_payload |
The payload for an AST_CONTROL_CC frame. More... | |
struct | cc_core_instance |
struct | cc_generic_agent_pvt |
struct | cc_monitor_backend |
struct | cc_monitor_backends |
struct | cc_monitor_tree |
The "tree" of interfaces that is dialed. More... | |
struct | cc_recall_ds_data |
struct | cc_state_change_args |
struct | cc_status_response_args |
struct | count_agents_cb_data |
struct | count_monitors_cb_data |
struct | dialed_cc_interfaces |
struct | extension_child_dialstring |
Data regarding an extension monitor's child's dialstrings. More... | |
struct | extension_monitor_pvt |
Private data for an extension monitor. More... | |
struct | generic_monitor_instance |
struct | generic_monitor_instance_list |
struct | generic_monitor_pvt |
private data for generic device monitor More... | |
struct | generic_tp_cb_data |
Defines | |
#define | CC_MAX_AGENTS_DEFAULT 5 |
#define | CC_MAX_MONITORS_DEFAULT 5 |
#define | CC_OFFER_TIMER_DEFAULT 20 |
#define | CC_RECALL_TIMER_DEFAULT 20 |
#define | CCBS_AVAILABLE_TIMER_DEFAULT 4800 |
#define | CCNR_AVAILABLE_TIMER_DEFAULT 7200 |
#define | GLOBAL_CC_MAX_REQUESTS_DEFAULT 20 |
Enumerations | |
enum | cc_state { CC_AVAILABLE, CC_CALLER_OFFERED, CC_CALLER_REQUESTED, CC_ACTIVE, CC_CALLEE_READY, CC_CALLER_BUSY, CC_RECALLING, CC_COMPLETE, CC_FAILED } |
The states used in the CCSS core state machine. More... | |
enum | match_flags { MATCH_NO_REQUEST = (1 << 0), MATCH_REQUEST = (1 << 1) } |
Functions | |
ast_cc_config_params * | __ast_cc_config_params_init (const char *file, int line, const char *function) |
Allocate and initialize an ast_cc_config_params structure. | |
static void | agent_destroy (void *data) |
static const char * | agent_policy_to_str (enum ast_cc_agent_policies policy) |
int | ast_cc_agent_accept_request (int core_id, const char *const debug,...) |
Accept inbound CC request. | |
ast_cc_agent * | ast_cc_agent_callback (int flags, ao2_callback_fn *function, void *args, const char *const type) |
Call a callback on all agents of a specific type. | |
int | ast_cc_agent_caller_available (int core_id, const char *const debug,...) |
Indicate that a previously unavailable caller has become available. | |
int | ast_cc_agent_caller_busy (int core_id, const char *debug,...) |
Indicate that the caller is busy. | |
int | ast_cc_agent_recalling (int core_id, const char *const debug,...) |
Tell the CC core that a caller is currently recalling. | |
int | ast_cc_agent_register (const struct ast_cc_agent_callbacks *callbacks) |
Register a set of agent callbacks with the core. | |
int | ast_cc_agent_set_interfaces_chanvar (struct ast_channel *chan) |
Set the first level CC_INTERFACES channel variable for a channel. | |
int | ast_cc_agent_status_response (int core_id, enum ast_device_state devstate) |
Response with a caller's current status. | |
void | ast_cc_agent_unregister (const struct ast_cc_agent_callbacks *callbacks) |
Unregister a set of agent callbacks with the core. | |
int | ast_cc_available_timer_expire (const void *data) |
Scheduler callback for available timer expiration. | |
int | ast_cc_build_frame (struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, enum ast_cc_service_type service, void *private_data, struct ast_frame *frame) |
Create a CC Control frame. | |
void | ast_cc_busy_interface (struct ast_channel *inbound, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, void *private_data) |
Callback made from ast_cc_callback for certain channel types. | |
void | ast_cc_call_failed (struct ast_channel *incoming, struct ast_channel *outgoing, const char *const dialstring) |
Make CCBS available in the case that ast_call fails. | |
int | ast_cc_call_init (struct ast_channel *chan, int *ignore_cc) |
Start the CC process on a call. | |
int | ast_cc_callback (struct ast_channel *inbound, const char *const tech, const char *const dest, ast_cc_callback_fn callback) |
Run a callback for potential matching destinations. | |
int | ast_cc_completed (struct ast_channel *chan, const char *const debug,...) |
Indicate recall has been acknowledged. | |
void | ast_cc_config_params_destroy (struct ast_cc_config_params *params) |
Free memory from CCSS configuration params. | |
void | ast_cc_copy_config_params (struct ast_cc_config_params *dest, const struct ast_cc_config_params *src) |
copy CCSS configuration parameters from one structure to another | |
void | ast_cc_default_config_params (struct ast_cc_config_params *params) |
Set the specified CC config params to default values. | |
void | ast_cc_extension_monitor_add_dialstring (struct ast_channel *incoming, const char *const dialstring, const char *const device_name) |
Add a child dialstring to an extension monitor. | |
int | ast_cc_failed (int core_id, const char *const debug,...) |
Indicate failure has occurred. | |
int | ast_cc_get_current_core_id (struct ast_channel *chan) |
Get the core id for the current call. | |
ast_cc_monitor * | ast_cc_get_monitor_by_recall_core_id (const int core_id, const char *const device_name) |
Get the associated monitor given the device name and core_id. | |
int | ast_cc_get_param (struct ast_cc_config_params *params, const char *const name, char *buf, size_t buf_len) |
get a CCSS configuration parameter, given its name | |
int | ast_cc_init (void) |
Initialize CCSS. | |
int | ast_cc_is_config_param (const char *const name) |
Is this a CCSS configuration parameter? | |
int | ast_cc_is_recall (struct ast_channel *chan, int *core_id, const char *const monitor_type) |
Decide if a call to a particular channel is a CC recall. | |
int | ast_cc_monitor_callee_available (const int core_id, const char *const debug,...) |
Alert the core that a device being monitored has become available. | |
int | ast_cc_monitor_count (const char *const name, const char *const type) |
Return the number of outstanding CC requests to a specific device. | |
int | ast_cc_monitor_failed (int core_id, const char *const monitor_name, const char *const debug,...) |
Indicate that a failure has occurred on a specific monitor. | |
int | ast_cc_monitor_party_b_free (int core_id) |
Alert a caller that though the callee has become free, the caller himself is not and may not call back. | |
int | ast_cc_monitor_register (const struct ast_cc_monitor_callbacks *callbacks) |
Register a set of monitor callbacks with the core. | |
int | ast_cc_monitor_request_acked (int core_id, const char *const debug,...) |
Indicate that an outbound entity has accepted our CC request. | |
int | ast_cc_monitor_status_request (int core_id) |
Request the status of a caller or callers. | |
int | ast_cc_monitor_stop_ringing (int core_id) |
Alert a caller to stop ringing. | |
void | ast_cc_monitor_unregister (const struct ast_cc_monitor_callbacks *callbacks) |
Unregister a set of monitor callbacks with the core. | |
int | ast_cc_offer (struct ast_channel *caller_chan) |
Offer CC to a caller. | |
int | ast_cc_request_is_within_limits (void) |
Check if the incoming CC request is within the bounds set by the cc_max_requests configuration option. | |
int | ast_cc_set_param (struct ast_cc_config_params *params, const char *const name, const char *const value) |
set a CCSS configuration parameter, given its name | |
const char * | ast_get_cc_agent_dialstring (struct ast_cc_config_params *config) |
Get the cc_agent_dialstring. | |
enum ast_cc_agent_policies | ast_get_cc_agent_policy (struct ast_cc_config_params *config) |
Get the cc_agent_policy. | |
const char * | ast_get_cc_callback_macro (struct ast_cc_config_params *config) |
Get the name of the callback_macro. | |
unsigned int | ast_get_cc_max_agents (struct ast_cc_config_params *config) |
Get the cc_max_agents. | |
unsigned int | ast_get_cc_max_monitors (struct ast_cc_config_params *config) |
Get the cc_max_monitors. | |
enum ast_cc_monitor_policies | ast_get_cc_monitor_policy (struct ast_cc_config_params *config) |
Get the cc_monitor_policy. | |
unsigned int | ast_get_cc_offer_timer (struct ast_cc_config_params *config) |
Get the cc_offer_timer. | |
unsigned int | ast_get_cc_recall_timer (struct ast_cc_config_params *config) |
Get the cc_recall_timer. | |
unsigned int | ast_get_ccbs_available_timer (struct ast_cc_config_params *config) |
Get the ccbs_available_timer. | |
unsigned int | ast_get_ccnr_available_timer (struct ast_cc_config_params *config) |
Get the ccnr_available_timer. | |
void | ast_handle_cc_control_frame (struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data) |
Properly react to a CC control frame. | |
void | ast_ignore_cc (struct ast_channel *chan) |
Mark the channel to ignore further CC activity. | |
int | ast_queue_cc_frame (struct ast_channel *chan, const char *monitor_type, const char *const dialstring, enum ast_cc_service_type service, void *private_data) |
Queue an AST_CONTROL_CC frame. | |
void | ast_set_cc_agent_dialstring (struct ast_cc_config_params *config, const char *const value) |
Set the cc_agent_dialstring. | |
int | ast_set_cc_agent_policy (struct ast_cc_config_params *config, enum ast_cc_agent_policies value) |
Set the cc_agent_policy. | |
void | ast_set_cc_callback_macro (struct ast_cc_config_params *config, const char *const value) |
Set the callback_macro name. | |
int | ast_set_cc_interfaces_chanvar (struct ast_channel *chan, const char *const extension) |
Set the CC_INTERFACES channel variable for a channel using an extension as a starting point. | |
void | ast_set_cc_max_agents (struct ast_cc_config_params *config, unsigned int value) |
Set the cc_max_agents. | |
void | ast_set_cc_max_monitors (struct ast_cc_config_params *config, unsigned int value) |
Set the cc_max_monitors. | |
int | ast_set_cc_monitor_policy (struct ast_cc_config_params *config, enum ast_cc_monitor_policies value) |
Set the cc_monitor_policy. | |
void | ast_set_cc_offer_timer (struct ast_cc_config_params *config, unsigned int value) |
Set the cc_offer_timer. | |
void | ast_set_cc_recall_timer (struct ast_cc_config_params *config, unsigned int value) |
Set the cc_recall_timer. | |
void | ast_set_ccbs_available_timer (struct ast_cc_config_params *config, unsigned int value) |
Set the ccbs_available_timer. | |
void | ast_set_ccnr_available_timer (struct ast_cc_config_params *config, unsigned int value) |
Set the ccnr_available_timer. | |
int | ast_setup_cc_recall_datastore (struct ast_channel *chan, const int core_id) |
Set up a CC recall datastore on a channel. | |
static void | build_cc_interfaces_chanvar (struct ast_cc_monitor *starting_point, struct ast_str *str) |
static void | call_destructor_with_no_monitor (const char *const monitor_type, void *private_data) |
static void | cancel_available_timer (struct cc_core_instance *core_instance) |
static int | cc_active (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_agent_callback_helper (void *obj, void *args, int flags) |
static struct ast_cc_agent * | cc_agent_init (struct ast_channel *caller_chan, const char *const caller_name, const int core_id, struct cc_monitor_tree *interface_tree) |
static int | cc_available (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_build_payload (struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *dialstring, enum ast_cc_service_type service, void *private_data, struct cc_control_payload *payload) |
static int | cc_callee_ready (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_caller_busy (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_caller_offered (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_caller_requested (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static int | cc_cli_output_status (void *data) |
static void | cc_cli_print_monitor_stats (struct ast_cc_monitor *monitor, int fd, int parent_id) |
static int | cc_complete (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static struct cc_core_instance * | cc_core_init_instance (struct ast_channel *caller_chan, struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data) |
static int | cc_core_instance_cmp_fn (void *obj, void *arg, int flags) |
static void | cc_core_instance_destructor (void *data) |
static int | cc_core_instance_hash_fn (const void *obj, const int flags) |
static struct ast_cc_monitor * | cc_device_monitor_init (const char *const device_name, const char *const dialstring, const struct cc_control_payload *cc_data, int core_id) |
static int | cc_do_state_change (void *datap) |
static void | cc_extension_monitor_change_is_valid (struct cc_core_instance *core_instance, unsigned int parent_id, const char *const device_name, int is_valid) |
static void | cc_extension_monitor_destructor (void *private_data) |
static struct ast_cc_monitor * | cc_extension_monitor_init (const char *const exten, const char *const context, const unsigned int parent_id) |
static int | cc_failed (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state) |
static void | cc_generic_agent_destructor (struct ast_cc_agent *agent) |
static int | cc_generic_agent_init (struct ast_cc_agent *agent, struct ast_channel *chan) |
static int | cc_generic_agent_recall (struct ast_cc_agent *agent) |
static void | cc_generic_agent_respond (struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason) |
static int | cc_generic_agent_start_monitoring (struct ast_cc_agent *agent) |
static int | cc_generic_agent_start_offer_timer (struct ast_cc_agent *agent) |
static int | cc_generic_agent_status_request (struct ast_cc_agent *agent) |
static int | cc_generic_agent_stop_offer_timer (struct ast_cc_agent *agent) |
static int | cc_generic_agent_stop_ringing (struct ast_cc_agent *agent) |
static int | cc_generic_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 const char * | cc_state_to_string (enum cc_state state) |
static int | cc_status_request (void *data) |
static int | cc_status_response (void *data) |
static int | cc_stop_ringing (void *data) |
static void | cc_unique_append (struct ast_str *str, const char *dialstring) |
static void * | cc_unref (void *obj, const char *debug) |
static int | cccancel_exec (struct ast_channel *chan, const char *data) |
static int | ccreq_exec (struct ast_channel *chan, const char *data) |
static void | check_callback_sanity (const struct ast_cc_agent_callbacks *callbacks) |
static char * | complete_core_id (const char *line, const char *word, int pos, int state) |
static long | count_agents (const char *const caller, const int core_id_exception) |
static int | count_agents_cb (void *obj, void *arg, void *data, int flags) |
static int | count_monitors_cb (void *obj, void *arg, int flags) |
static struct generic_monitor_instance_list * | create_new_generic_list (struct ast_cc_monitor *monitor) |
static void | dialed_cc_interfaces_destroy (void *data) |
static void * | dialed_cc_interfaces_duplicate (void *data) |
static struct extension_monitor_pvt * | extension_monitor_pvt_init (void) |
static struct ast_cc_agent_callbacks * | find_agent_callbacks (struct ast_channel *chan) |
static struct cc_core_instance * | find_cc_core_instance (const int core_id) |
static struct generic_monitor_instance_list * | find_generic_monitor_instance_list (const char *const device_name) |
static struct ast_cc_monitor_callbacks * | find_monitor_callbacks (const char *const type) |
static void | generic_agent_devstate_cb (const struct ast_event *event, void *userdata) |
static int | generic_agent_devstate_unsubscribe (void *data) |
static int | generic_monitor_cmp_fn (void *obj, void *arg, int flags) |
static void | generic_monitor_devstate_cb (const struct ast_event *event, void *userdata) |
static int | generic_monitor_devstate_tp_cb (void *data) |
static int | generic_monitor_hash_fn (const void *obj, const int flags) |
static void | generic_monitor_instance_list_destructor (void *obj) |
static void * | generic_recall (void *data) |
static char * | handle_cc_kill (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cc_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | has_device_monitors (struct cc_core_instance *core_instance) |
check if the core instance has any device monitors | |
static void | initialize_cc_max_requests (void) |
static int | is_state_change_valid (enum cc_state current_state, const enum cc_state new_state, struct ast_cc_agent *agent) |
static int | kill_cores (void *obj, void *arg, int flags) |
static void | kill_duplicate_offers (char *caller) |
static int | match_agent (void *obj, void *arg, void *data, int flags) |
static const char * | monitor_policy_to_str (enum ast_cc_monitor_policies policy) |
static int | offer_timer_expire (const void *data) |
static int | print_stats_cb (void *obj, void *arg, int flags) |
static void | request_cc (struct cc_core_instance *core_instance) |
static enum ast_cc_agent_policies | str_to_agent_policy (const char *const value) |
static enum ast_cc_monitor_policies | str_to_monitor_policy (const char *const value) |
static void | suspend (struct cc_core_instance *core_instance) |
static void | unsuspend (struct cc_core_instance *core_instance) |
Variables | |
static struct ast_cli_entry | cc_cli [] |
static struct ao2_container * | cc_core_instances |
static const int | CC_CORE_INSTANCES_BUCKETS = 17 |
static struct ast_taskprocessor * | cc_core_taskprocessor |
static struct ast_cc_config_params | cc_default_params |
static int | cc_logger_level |
static const char * | CC_LOGGER_LEVEL_NAME = "CC" |
static int | cc_request_count |
static struct ast_sched_thread * | cc_sched_thread |
struct { | |
enum ast_cc_service_type service | |
const char * service_string | |
} | cc_service_to_string_map [] |
struct { | |
enum cc_state state | |
const char * state_string | |
} | cc_state_to_string_map [] |
static const char * | cccancel_app = "CallCompletionCancel" |
static const char * | ccreq_app = "CallCompletionRequest" |
static int | core_id_counter |
static int | dialed_cc_interface_counter |
static struct ast_datastore_info | dialed_cc_interfaces_info |
static struct ast_cc_agent_callbacks | generic_agent_callbacks |
static struct ast_cc_monitor_callbacks | generic_monitor_cbs |
ao2_container * | generic_monitors |
static unsigned int | global_cc_max_requests |
static struct ast_datastore_info | recall_ds_info |
static int(*const []) | state_change_funcs (struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state) |
Definition in file ccss.c.
#define GLOBAL_CC_MAX_REQUESTS_DEFAULT 20 |
enum cc_state |
The states used in the CCSS core state machine.
Definition at line 167 of file ccss.c.
00167 { 00168 /*! Entered when it is determined that CCSS may be used for the call */ 00169 CC_AVAILABLE, 00170 /*! Entered when a CCSS agent has offered CCSS to a caller */ 00171 CC_CALLER_OFFERED, 00172 /*! Entered when a CCSS agent confirms that a caller has 00173 * requested CCSS */ 00174 CC_CALLER_REQUESTED, 00175 /*! Entered when a CCSS monitor confirms acknowledgment of an 00176 * outbound CCSS request */ 00177 CC_ACTIVE, 00178 /*! Entered when a CCSS monitor alerts the core that the called party 00179 * has become available */ 00180 CC_CALLEE_READY, 00181 /*! Entered when a CCSS agent alerts the core that the calling party 00182 * may not be recalled because he is unavailable 00183 */ 00184 CC_CALLER_BUSY, 00185 /*! Entered when a CCSS agent alerts the core that the calling party 00186 * is attempting to recall the called party 00187 */ 00188 CC_RECALLING, 00189 /*! Entered when an application alerts the core that the calling party's 00190 * recall attempt has had a call progress response indicated 00191 */ 00192 CC_COMPLETE, 00193 /*! Entered any time that something goes wrong during the process, thus 00194 * resulting in the failure of the attempted CCSS transaction. Note also 00195 * that cancellations of CC are treated as failures. 00196 */ 00197 CC_FAILED, 00198 };
enum match_flags |
Definition at line 455 of file ccss.c.
00455 { 00456 /* Only match agents that have not yet 00457 * made a CC request 00458 */ 00459 MATCH_NO_REQUEST = (1 << 0), 00460 /* Only match agents that have made 00461 * a CC request 00462 */ 00463 MATCH_REQUEST = (1 << 1), 00464 };
struct ast_cc_config_params* __ast_cc_config_params_init | ( | const char * | file, | |
int | line, | |||
const char * | function | |||
) |
Allocate and initialize an ast_cc_config_params structure.
NULL | Unable to allocate the structure | |
non-NULL | A pointer to the newly allocated and initialized structure |
Definition at line 559 of file ccss.c.
References __ast_malloc(), ast_cc_default_config_params(), and ast_malloc.
00560 { 00561 #if defined(__AST_DEBUG_MALLOC) 00562 struct ast_cc_config_params *params = __ast_malloc(sizeof(*params), file, line, function); 00563 #else 00564 struct ast_cc_config_params *params = ast_malloc(sizeof(*params)); 00565 #endif 00566 00567 if (!params) { 00568 return NULL; 00569 } 00570 00571 ast_cc_default_config_params(params); 00572 return params; 00573 }
static void agent_destroy | ( | void * | data | ) | [static] |
Definition at line 2271 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().
02272 { 02273 struct ast_cc_agent *agent = data; 02274 02275 if (agent->callbacks) { 02276 agent->callbacks->destructor(agent); 02277 } 02278 ast_cc_config_params_destroy(agent->cc_params); 02279 }
static const char* agent_policy_to_str | ( | enum ast_cc_agent_policies | policy | ) | [static] |
Definition at line 610 of file ccss.c.
References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, and AST_CC_AGENT_NEVER.
Referenced by ast_cc_get_param().
00611 { 00612 switch (policy) { 00613 case AST_CC_AGENT_NEVER: 00614 return "never"; 00615 case AST_CC_AGENT_NATIVE: 00616 return "native"; 00617 case AST_CC_AGENT_GENERIC: 00618 return "generic"; 00619 default: 00620 /* This should never happen... */ 00621 return ""; 00622 } 00623 }
int ast_cc_agent_accept_request | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Accept inbound CC request.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3495 of file ccss.c.
References CC_CALLER_REQUESTED, and cc_request_state_change().
Referenced by ccreq_exec(), handle_cc_subscribe(), and sig_pri_handle_cis_subcmds().
03496 { 03497 va_list ap; 03498 int res; 03499 03500 va_start(ap, debug); 03501 res = cc_request_state_change(CC_CALLER_REQUESTED, core_id, debug, ap); 03502 va_end(ap); 03503 return res; 03504 }
struct ast_cc_agent* ast_cc_agent_callback | ( | int | flags, | |
ao2_callback_fn * | function, | |||
void * | arg, | |||
const char *const | type | |||
) |
Call a callback on all agents of a specific type.
Since the container of CC core instances is private, and so are the items which the container contains, we have to provide an ao2_callback-like method so that a specific agent may be found or so that an operation can be made on all agents of a particular type. The first three arguments should be familiar to anyone who has used ao2_callback. The final argument is the type of agent you wish to have the callback called on.
flags | astobj2 search flags | |
function | an ao2 callback function to call | |
arg | the argument to the callback function | |
type | The type of agents to call the callback on |
Definition at line 442 of file ccss.c.
References cc_core_instance::agent, ao2_t_callback, cc_agent_callback_helper(), cc_core_instances, cc_ref(), cc_unref(), and cc_callback_helper::function.
Referenced by find_sip_cc_agent_by_notify_uri(), find_sip_cc_agent_by_original_callid(), find_sip_cc_agent_by_subscribe_uri(), and sig_pri_find_cc_agent_by_cc_id().
00443 { 00444 struct cc_callback_helper helper = {.function = function, .args = args, .type = type}; 00445 struct cc_core_instance *core_instance; 00446 if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper, 00447 "Calling provided agent callback function"))) { 00448 struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent"); 00449 cc_unref(core_instance, "agent callback done with the core_instance"); 00450 return agent; 00451 } 00452 return NULL; 00453 }
int ast_cc_agent_caller_available | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate that a previously unavailable caller has become available.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3539 of file ccss.c.
References CC_ACTIVE, and cc_request_state_change().
Referenced by cc_esc_publish_handler(), generic_agent_devstate_cb(), and sig_pri_handle_cis_subcmds().
03540 { 03541 va_list ap; 03542 int res; 03543 03544 va_start(ap, debug); 03545 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap); 03546 va_end(ap); 03547 return res; 03548 }
int ast_cc_agent_caller_busy | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate that the caller is busy.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3528 of file ccss.c.
References CC_CALLER_BUSY, and cc_request_state_change().
Referenced by cc_esc_publish_handler(), cc_generic_agent_recall(), sig_pri_handle_cis_subcmds(), and sip_cc_agent_recall().
03529 { 03530 va_list ap; 03531 int res; 03532 03533 va_start(ap, debug); 03534 res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap); 03535 va_end(ap); 03536 return res; 03537 }
int ast_cc_agent_recalling | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Tell the CC core that a caller is currently recalling.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3550 of file ccss.c.
References CC_RECALLING, and cc_request_state_change().
Referenced by generic_recall(), get_destination(), and sig_pri_handle_subcmds().
03551 { 03552 va_list ap; 03553 int res; 03554 03555 va_start(ap, debug); 03556 res = cc_request_state_change(CC_RECALLING, core_id, debug, ap); 03557 va_end(ap); 03558 return res; 03559 }
int ast_cc_agent_register | ( | const struct ast_cc_agent_callbacks * | callbacks | ) |
Register a set of agent callbacks with the core.
callbacks | The callbacks used by the agent implementation |
0 | Successfully registered | |
-1 | Failure to register |
Definition at line 946 of file ccss.c.
References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and cc_monitor_backend::next.
Referenced by ast_cc_init(), and load_module().
00947 { 00948 struct cc_agent_backend *backend = ast_calloc(1, sizeof(*backend)); 00949 00950 if (!backend) { 00951 return -1; 00952 } 00953 00954 backend->callbacks = callbacks; 00955 AST_RWLIST_WRLOCK(&cc_agent_backends); 00956 AST_RWLIST_INSERT_TAIL(&cc_agent_backends, backend, next); 00957 AST_RWLIST_UNLOCK(&cc_agent_backends); 00958 return 0; 00959 }
int ast_cc_agent_set_interfaces_chanvar | ( | struct ast_channel * | chan | ) |
Set the first level CC_INTERFACES channel variable for a channel.
This function will lock the channel as well as the list of monitors stored on the channel's CC recall datastore, though neither are held at the same time. Callers of this function should be aware of potential lock ordering problems that may arise.
chan | The channel to set the CC_INTERFACES variable on |
Definition at line 3350 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_free, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_str_buffer(), ast_str_create(), build_cc_interfaces_chanvar(), cc_recall_ds_data::core_id, ast_datastore::data, cc_recall_ds_data::interface_tree, monitor, pbx_builtin_setvar_helper(), recall_ds_info, and str.
Referenced by generic_recall(), handle_request_invite(), and sig_pri_handle_subcmds().
03351 { 03352 struct ast_datastore *recall_datastore; 03353 struct cc_monitor_tree *interface_tree; 03354 struct ast_cc_monitor *monitor; 03355 struct cc_recall_ds_data *recall_data; 03356 struct ast_str *str = ast_str_create(64); 03357 int core_id; 03358 03359 if (!str) { 03360 return -1; 03361 } 03362 03363 ast_channel_lock(chan); 03364 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03365 ast_channel_unlock(chan); 03366 ast_free(str); 03367 return -1; 03368 } 03369 recall_data = recall_datastore->data; 03370 interface_tree = recall_data->interface_tree; 03371 core_id = recall_data->core_id; 03372 ast_channel_unlock(chan); 03373 03374 AST_LIST_LOCK(interface_tree); 03375 monitor = AST_LIST_FIRST(interface_tree); 03376 build_cc_interfaces_chanvar(monitor, str); 03377 AST_LIST_UNLOCK(interface_tree); 03378 03379 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str)); 03380 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n", 03381 core_id, ast_str_buffer(str)); 03382 03383 ast_free(str); 03384 return 0; 03385 }
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 3815 of file ccss.c.
References args, ast_calloc, ast_free, ast_taskprocessor_push(), cc_core_taskprocessor, cc_status_response(), cc_unref(), and find_cc_core_instance().
Referenced by cc_generic_agent_status_request(), sig_pri_handle_cis_subcmds(), and sip_cc_agent_status_request().
03816 { 03817 struct cc_status_response_args *args; 03818 struct cc_core_instance *core_instance; 03819 int res; 03820 03821 args = ast_calloc(1, sizeof(*args)); 03822 if (!args) { 03823 return -1; 03824 } 03825 03826 core_instance = find_cc_core_instance(core_id); 03827 if (!core_instance) { 03828 ast_free(args); 03829 return -1; 03830 } 03831 03832 args->core_instance = core_instance; 03833 args->devstate = devstate; 03834 03835 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_response, args); 03836 if (res) { 03837 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03838 ast_free(args); 03839 } 03840 return res; 03841 }
void ast_cc_agent_unregister | ( | const struct ast_cc_agent_callbacks * | callbacks | ) |
Unregister a set of agent callbacks with the core.
callbacks | The callbacks used by the agent implementation |
0 | Successfully unregistered | |
-1 | Failure to unregister |
Definition at line 961 of file ccss.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cc_monitor_backend::callbacks, cc_agent_backend::callbacks, and cc_monitor_backend::next.
Referenced by __unload_module().
00962 { 00963 struct cc_agent_backend *backend; 00964 AST_RWLIST_WRLOCK(&cc_agent_backends); 00965 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_agent_backends, backend, next) { 00966 if (backend->callbacks == callbacks) { 00967 AST_RWLIST_REMOVE_CURRENT(next); 00968 ast_free(backend); 00969 break; 00970 } 00971 } 00972 AST_RWLIST_TRAVERSE_SAFE_END; 00973 AST_RWLIST_UNLOCK(&cc_agent_backends); 00974 }
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 1229 of file ccss.c.
References ast_cc_monitor_failed(), cc_unref(), and monitor.
Referenced by cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().
01230 { 01231 struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data; 01232 int res; 01233 monitor->available_timer_id = -1; 01234 res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor"); 01235 cc_unref(monitor, "Unref reference from scheduler\n"); 01236 return res; 01237 }
int ast_cc_build_frame | ( | struct ast_channel * | chan, | |
struct ast_cc_config_params * | cc_params, | |||
const char * | monitor_type, | |||
const char *const | device_name, | |||
const char *const | dialstring, | |||
enum ast_cc_service_type | service, | |||
void * | private_data, | |||
struct ast_frame * | frame | |||
) |
Create a CC Control frame.
chan | A channel involved in the call. What we want is on a datastore on both incoming and outgoing so either may be provided | |
cc_params | The CC configuration parameters for the outbound target | |
monitor_type | The type of monitor to use when CC is requested | |
device_name | The name of the outbound target device. | |
dialstring | The dial string used when calling this specific interface | |
service | What kind of CC service is being offered. (CCBS/CCNR/etc...) | |
private_data | If a native monitor is being used, and some channel-driver-specific private data has been allocated, then this parameter should contain a pointer to that data. If using a generic monitor, this parameter should remain NULL. Note that if this function should fail at some point, it is the responsibility of the caller to free the private data upon return. | |
[out] | frame | The frame we will be returning to the caller. It is vital that ast_frame_free be called on this frame since the payload will be allocated on the heap. |
-1 | Failure. At some point there was a failure. Do not attempt to use the frame in this case. | |
0 | Success |
Definition at line 3898 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().
03902 { 03903 struct cc_control_payload *payload = ast_calloc(1, sizeof(*payload)); 03904 03905 if (!payload) { 03906 return -1; 03907 } 03908 if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) { 03909 /* Something screwed up, we can't make a frame with this */ 03910 ast_free(payload); 03911 return -1; 03912 } 03913 frame->frametype = AST_FRAME_CONTROL; 03914 frame->subclass.integer = AST_CONTROL_CC; 03915 frame->data.ptr = payload; 03916 frame->datalen = sizeof(*payload); 03917 frame->mallocd = AST_MALLOCD_DATA; 03918 return 0; 03919 }
void ast_cc_busy_interface | ( | struct ast_channel * | inbound, | |
struct ast_cc_config_params * | cc_params, | |||
const char * | monitor_type, | |||
const char *const | device_name, | |||
const char *const | dialstring, | |||
void * | private_data | |||
) |
Callback made from ast_cc_callback for certain channel types.
inbound | Incoming asterisk channel. | |
cc_params | The CC configuration parameters for the outbound target | |
monitor_type | The type of monitor to use when CC is requested | |
device_name | The name of the outbound target device. | |
dialstring | The dial string used when calling this specific interface | |
private_data | If a native monitor is being used, and some channel-driver-specific private data has been allocated, then this parameter should contain a pointer to that data. If using a generic monitor, this parameter should remain NULL. Note that if this function should fail at some point, it is the responsibility of the caller to free the private data upon return. |
This function creates a CC control frame payload, simulating the act of reading it from the nonexistent outgoing channel's frame queue. We then handle this simulated frame just as we would a normal CC frame which had actually been queued by the channel driver.
Definition at line 3954 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().
03956 { 03957 struct cc_control_payload payload; 03958 if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) { 03959 /* Something screwed up. Don't try to handle this payload */ 03960 call_destructor_with_no_monitor(monitor_type, private_data); 03961 return; 03962 } 03963 ast_handle_cc_control_frame(inbound, NULL, &payload); 03964 }
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 3921 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().
03922 { 03923 char device_name[AST_CHANNEL_NAME]; 03924 struct cc_control_payload payload; 03925 struct ast_cc_config_params *cc_params; 03926 03927 if (outgoing->hangupcause != AST_CAUSE_BUSY && outgoing->hangupcause != AST_CAUSE_CONGESTION) { 03928 /* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call 03929 * failing is something other than busy or congestion 03930 */ 03931 return; 03932 } 03933 03934 cc_params = ast_channel_get_cc_config_params(outgoing); 03935 if (!cc_params) { 03936 return; 03937 } 03938 if (ast_get_cc_monitor_policy(cc_params) != AST_CC_MONITOR_GENERIC) { 03939 /* This sort of CCBS only works if using generic CC. For native, we would end up sending 03940 * a CC request for a non-existent call. The far end will reject this every time 03941 */ 03942 return; 03943 } 03944 03945 ast_channel_get_device_name(outgoing, device_name, sizeof(device_name)); 03946 if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name, 03947 dialstring, AST_CC_CCBS, NULL, &payload)) { 03948 /* Something screwed up, we can't make a frame with this */ 03949 return; 03950 } 03951 ast_handle_cc_control_frame(incoming, outgoing, &payload); 03952 }
int ast_cc_call_init | ( | struct ast_channel * | chan, | |
int * | ignore_cc | |||
) |
Start the CC process on a call.
The ignore_cc parameter is a convenience parameter. It can save an application the trouble of trying to call CC APIs when it knows that it should just ignore further attempts at CC actions.
chan | The inbound channel calling the CC-capable application. | |
[out] | ignore_cc | Will be set non-zero if no further CC actions need to be taken |
0 | Success | |
-1 | Failure |
Definition at line 2136 of file ccss.c.
References AST_CC_AGENT_NEVER, ast_channel_datastore_find(), ast_channel_get_cc_config_params(), ast_channel_lock, ast_channel_unlock, ast_get_cc_agent_policy(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log_dynamic_level, cc_extension_monitor_init(), cc_interfaces_datastore_init(), cc_ref(), cc_unref(), ast_channel::context, dialed_cc_interfaces::core_id, ast_datastore::data, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces_info, ast_channel::exten, dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, ast_channel::macrocontext, ast_channel::macroexten, monitor, ast_channel::name, cc_monitor_backend::next, and S_OR.
Referenced by dial_exec_full().
02137 { 02138 /* There are three situations to deal with here: 02139 * 02140 * 1. The channel does not have a dialed_cc_interfaces datastore on 02141 * it. This means that this is the first time that Dial has 02142 * been called. We need to create/initialize the datastore. 02143 * 02144 * 2. The channel does have a cc_interface datastore on it and 02145 * the "ignore" indicator is 0. This means that a Local channel 02146 * was called by a "parent" dial. We can check the datastore's 02147 * parent field to see who the root of this particular dial tree 02148 * is. 02149 * 02150 * 3. The channel does have a cc_interface datastore on it and 02151 * the "ignore" indicator is 1. This means that a second Dial call 02152 * is being made from an extension. In this case, we do not 02153 * want to make any additions/modifications to the datastore. We 02154 * will instead set a flag to indicate that CCSS is completely 02155 * disabled for this Dial attempt. 02156 */ 02157 02158 struct ast_datastore *cc_interfaces_datastore; 02159 struct dialed_cc_interfaces *interfaces; 02160 struct ast_cc_monitor *monitor; 02161 struct ast_cc_config_params *cc_params; 02162 02163 ast_channel_lock(chan); 02164 02165 cc_params = ast_channel_get_cc_config_params(chan); 02166 if (!cc_params) { 02167 ast_channel_unlock(chan); 02168 return -1; 02169 } 02170 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) { 02171 /* We can't offer CC to this caller anyway, so don't bother with CC on this call 02172 */ 02173 *ignore_cc = 1; 02174 ast_channel_unlock(chan); 02175 ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", chan->name); 02176 return 0; 02177 } 02178 02179 if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) { 02180 /* Situation 1 has occurred */ 02181 ast_channel_unlock(chan); 02182 return cc_interfaces_datastore_init(chan); 02183 } 02184 interfaces = cc_interfaces_datastore->data; 02185 ast_channel_unlock(chan); 02186 02187 if (interfaces->ignore) { 02188 /* Situation 3 has occurred */ 02189 *ignore_cc = 1; 02190 ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n"); 02191 return 0; 02192 } 02193 02194 /* Situation 2 has occurred */ 02195 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten), 02196 S_OR(chan->macrocontext, chan->context), interfaces->dial_parent_id))) { 02197 return -1; 02198 } 02199 monitor->core_id = interfaces->core_id; 02200 AST_LIST_LOCK(interfaces->interface_tree); 02201 cc_ref(monitor, "monitor tree's reference to the monitor"); 02202 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next); 02203 AST_LIST_UNLOCK(interfaces->interface_tree); 02204 interfaces->dial_parent_id = monitor->id; 02205 cc_unref(monitor, "Unref monitor's allocation reference"); 02206 return 0; 02207 }
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 3966 of file ccss.c.
References ast_get_channel_tech(), and ast_channel_tech::cc_callback.
Referenced by dial_exec_full().
03967 { 03968 const struct ast_channel_tech *chantech = ast_get_channel_tech(tech); 03969 03970 if (chantech && chantech->cc_callback) { 03971 chantech->cc_callback(inbound, dest, callback); 03972 } 03973 03974 return 0; 03975 }
int ast_cc_completed | ( | struct ast_channel * | chan, | |
const char *const | debug, | |||
... | ||||
) |
Indicate recall has been acknowledged.
chan | The inbound channel making the CC recall | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3561 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, CC_COMPLETE, cc_request_state_change(), cc_recall_ds_data::core_id, ast_datastore::data, cc_recall_ds_data::ignore, cc_recall_ds_data::nested, and recall_ds_info.
03562 { 03563 struct ast_datastore *recall_datastore; 03564 struct cc_recall_ds_data *recall_data; 03565 int core_id; 03566 va_list ap; 03567 int res; 03568 03569 ast_channel_lock(chan); 03570 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03571 /* Silly! Why did you call this function if there's no recall DS? */ 03572 ast_channel_unlock(chan); 03573 return -1; 03574 } 03575 recall_data = recall_datastore->data; 03576 if (recall_data->nested || recall_data->ignore) { 03577 /* If this is being called from a nested Dial, it is too 03578 * early to determine if the recall has actually completed. 03579 * The outermost dial is the only one with the authority to 03580 * declare the recall to be complete. 03581 * 03582 * Similarly, if this function has been called when the 03583 * recall has progressed beyond the first dial, this is not 03584 * a legitimate time to declare the recall to be done. In fact, 03585 * that should have been done already. 03586 */ 03587 ast_channel_unlock(chan); 03588 return -1; 03589 } 03590 core_id = recall_data->core_id; 03591 ast_channel_unlock(chan); 03592 va_start(ap, debug); 03593 res = cc_request_state_change(CC_COMPLETE, core_id, debug, ap); 03594 va_end(ap); 03595 return res; 03596 }
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 575 of file ccss.c.
References ast_free.
Referenced by __sip_destroy(), agent_destroy(), ast_channel_cc_params_init(), cc_interface_destroy(), channel_cc_params_destroy(), destroy_dahdi_pvt(), setup_dahdi(), and sip_destroy_peer().
00576 { 00577 ast_free(params); 00578 }
void ast_cc_copy_config_params | ( | struct ast_cc_config_params * | dest, | |
const struct ast_cc_config_params * | src | |||
) |
copy CCSS configuration parameters from one structure to another
src | The structure from which data is copied | |
dest | The structure to which data is copied |
Definition at line 737 of file ccss.c.
Referenced by ast_channel_cc_params_init(), cc_agent_init(), cc_build_payload(), cc_device_monitor_init(), channel_cc_params_copy(), check_peer_ok(), create_addr_from_peer(), dahdi_new(), deep_copy_dahdi_chan_conf(), and duplicate_pseudo().
void ast_cc_default_config_params | ( | struct ast_cc_config_params * | params | ) |
Set the specified CC config params to default values.
params | CC config params to set to default values. |
Definition at line 554 of file ccss.c.
References cc_default_params.
Referenced by __ast_cc_config_params_init().
00555 { 00556 *params = cc_default_params; 00557 }
void ast_cc_extension_monitor_add_dialstring | ( | struct ast_channel * | incoming, | |
const char *const | dialstring, | |||
const char *const | device_name | |||
) |
Add a child dialstring to an extension monitor.
incoming | The caller's channel | |
dialstring | The dialstring used when requesting the outbound channel | |
device_name | The device name associated with the requested outbound channel |
void |
Definition at line 1725 of file ccss.c.
References ast_calloc, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, extension_monitor_pvt::child_dialstrings, ast_datastore::data, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces_info, id, dialed_cc_interfaces::interface_tree, monitor, and cc_monitor_backend::next.
Referenced by dial_exec_full().
01726 { 01727 struct ast_datastore *cc_datastore; 01728 struct dialed_cc_interfaces *cc_interfaces; 01729 struct ast_cc_monitor *monitor; 01730 struct extension_monitor_pvt *extension_pvt; 01731 struct extension_child_dialstring *child_dialstring; 01732 struct cc_monitor_tree *interface_tree; 01733 int id; 01734 01735 ast_channel_lock(incoming); 01736 if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) { 01737 ast_channel_unlock(incoming); 01738 return; 01739 } 01740 01741 cc_interfaces = cc_datastore->data; 01742 interface_tree = cc_interfaces->interface_tree; 01743 id = cc_interfaces->dial_parent_id; 01744 ast_channel_unlock(incoming); 01745 01746 AST_LIST_LOCK(interface_tree); 01747 AST_LIST_TRAVERSE(interface_tree, monitor, next) { 01748 if (monitor->id == id) { 01749 break; 01750 } 01751 } 01752 01753 if (!monitor) { 01754 AST_LIST_UNLOCK(interface_tree); 01755 return; 01756 } 01757 01758 extension_pvt = monitor->private_data; 01759 if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) { 01760 AST_LIST_UNLOCK(interface_tree); 01761 return; 01762 } 01763 ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring)); 01764 ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name)); 01765 child_dialstring->is_valid = 1; 01766 AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next); 01767 AST_LIST_UNLOCK(interface_tree); 01768 }
int ast_cc_failed | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate failure has occurred.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3598 of file ccss.c.
References CC_FAILED, and cc_request_state_change().
Referenced by cancel_available_timer(), cc_caller_offered(), cc_caller_requested(), cc_monitor_failed(), cccancel_exec(), ccreq_exec(), generic_recall(), handle_cc_subscribe(), kill_cores(), offer_timer_expire(), request_cc(), sig_pri_cc_agent_req_rsp(), sig_pri_cc_link_canceled(), sig_pri_handle_cis_subcmds(), sip_offer_timer_expire(), suspend(), unsuspend(), and wait_for_answer().
03599 { 03600 va_list ap; 03601 int res; 03602 03603 va_start(ap, debug); 03604 res = cc_request_state_change(CC_FAILED, core_id, debug, ap); 03605 va_end(ap); 03606 return res; 03607 }
int ast_cc_get_current_core_id | ( | struct ast_channel * | chan | ) |
Get the core id for the current call.
The channel given to this function may be an inbound or outbound channel. Both will have the necessary info on it.
chan | The channel from which to get the core_id. |
core_id | on success | |
-1 | Failure |
Definition at line 2214 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, dialed_cc_interfaces::core_id, ast_datastore::data, dialed_cc_interfaces_info, and dialed_cc_interfaces::ignore.
Referenced by sig_pri_cc_available(), sig_pri_cc_generic_check(), and sip_handle_cc().
02215 { 02216 struct ast_datastore *datastore; 02217 struct dialed_cc_interfaces *cc_interfaces; 02218 int core_id_return; 02219 02220 ast_channel_lock(chan); 02221 if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) { 02222 ast_channel_unlock(chan); 02223 return -1; 02224 } 02225 02226 cc_interfaces = datastore->data; 02227 core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id; 02228 ast_channel_unlock(chan); 02229 return core_id_return; 02230 02231 }
struct ast_cc_monitor* ast_cc_get_monitor_by_recall_core_id | ( | const int | core_id, | |
const char *const | device_name | |||
) |
Get the associated monitor given the device name and core_id.
core_id | The core ID to which this recall corresponds. This likely will have been obtained using the ast_cc_is_recall function | |
device_name | Which device to find the monitor for. |
NULL | Appropriate monitor does not exist | |
non-NULL | The monitor to use for this recall |
Definition at line 3238 of file ccss.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, cc_ref(), cc_unref(), ast_cc_interface::device_name, find_cc_core_instance(), ast_cc_monitor::interface, cc_core_instance::monitors, and cc_monitor_backend::next.
Referenced by sig_pri_call(), sig_pri_cc_generic_check(), and sip_call().
03239 { 03240 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03241 struct ast_cc_monitor *monitor_iter; 03242 03243 if (!core_instance) { 03244 return NULL; 03245 } 03246 03247 AST_LIST_LOCK(core_instance->monitors); 03248 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 03249 if (!strcmp(monitor_iter->interface->device_name, device_name)) { 03250 /* Found a monitor. */ 03251 cc_ref(monitor_iter, "Hand the requester of the monitor a reference"); 03252 break; 03253 } 03254 } 03255 AST_LIST_UNLOCK(core_instance->monitors); 03256 cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id"); 03257 return monitor_iter; 03258 }
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 641 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().
00643 { 00644 const char *value = NULL; 00645 00646 if (!strcasecmp(name, "cc_callback_macro")) { 00647 value = ast_get_cc_callback_macro(params); 00648 } else if (!strcasecmp(name, "cc_agent_policy")) { 00649 value = agent_policy_to_str(ast_get_cc_agent_policy(params)); 00650 } else if (!strcasecmp(name, "cc_monitor_policy")) { 00651 value = monitor_policy_to_str(ast_get_cc_monitor_policy(params)); 00652 } else if (!strcasecmp(name, "cc_agent_dialstring")) { 00653 value = ast_get_cc_agent_dialstring(params); 00654 } 00655 if (value) { 00656 ast_copy_string(buf, value, buf_len); 00657 return 0; 00658 } 00659 00660 /* The rest of these are all ints of some sort and require some 00661 * snprintf-itude 00662 */ 00663 00664 if (!strcasecmp(name, "cc_offer_timer")) { 00665 snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params)); 00666 } else if (!strcasecmp(name, "ccnr_available_timer")) { 00667 snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params)); 00668 } else if (!strcasecmp(name, "ccbs_available_timer")) { 00669 snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params)); 00670 } else if (!strcasecmp(name, "cc_max_agents")) { 00671 snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params)); 00672 } else if (!strcasecmp(name, "cc_max_monitors")) { 00673 snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params)); 00674 } else if (!strcasecmp(name, "cc_recall_timer")) { 00675 snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params)); 00676 } else { 00677 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name); 00678 return -1; 00679 } 00680 00681 return 0; 00682 }
int ast_cc_init | ( | void | ) |
Initialize CCSS.
0 | Success | |
nonzero | Failure |
Definition at line 4298 of file ccss.c.
References ao2_t_container_alloc, ARRAY_LEN, ast_cc_agent_register(), ast_cc_monitor_register(), ast_cli_register_multiple(), ast_logger_register_level(), ast_register_application2(), ast_sched_thread_create(), ast_taskprocessor_get(), cc_cli, cc_core_instance_cmp_fn(), cc_core_instance_hash_fn(), cc_core_instances, cc_core_taskprocessor, cc_sched_thread, cccancel_exec(), ccreq_exec(), generic_agent_callbacks, generic_monitor_cbs, generic_monitor_cmp_fn(), generic_monitor_hash_fn(), generic_monitors, initialize_cc_max_requests(), and TPS_REF_DEFAULT.
Referenced by main().
04299 { 04300 int res; 04301 04302 if (!(cc_core_instances = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS, 04303 cc_core_instance_hash_fn, cc_core_instance_cmp_fn, 04304 "Create core instance container"))) { 04305 return -1; 04306 } 04307 if (!(generic_monitors = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS, 04308 generic_monitor_hash_fn, generic_monitor_cmp_fn, 04309 "Create generic monitor container"))) { 04310 return -1; 04311 } 04312 if (!(cc_core_taskprocessor = ast_taskprocessor_get("CCSS core", TPS_REF_DEFAULT))) { 04313 return -1; 04314 } 04315 if (!(cc_sched_thread = ast_sched_thread_create())) { 04316 return -1; 04317 } 04318 res = ast_register_application2(ccreq_app, ccreq_exec, NULL, NULL, NULL); 04319 res |= ast_register_application2(cccancel_app, cccancel_exec, NULL, NULL, NULL); 04320 res |= ast_cc_monitor_register(&generic_monitor_cbs); 04321 res |= ast_cc_agent_register(&generic_agent_callbacks); 04322 ast_cli_register_multiple(cc_cli, ARRAY_LEN(cc_cli)); 04323 cc_logger_level = ast_logger_register_level(CC_LOGGER_LEVEL_NAME); 04324 dialed_cc_interface_counter = 1; 04325 initialize_cc_max_requests(); 04326 return res; 04327 }
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 723 of file ccss.c.
Referenced by build_peer().
00724 { 00725 return (!strcasecmp(name, "cc_agent_policy") || 00726 !strcasecmp(name, "cc_monitor_policy") || 00727 !strcasecmp(name, "cc_offer_timer") || 00728 !strcasecmp(name, "ccnr_available_timer") || 00729 !strcasecmp(name, "ccbs_available_timer") || 00730 !strcasecmp(name, "cc_max_agents") || 00731 !strcasecmp(name, "cc_max_monitors") || 00732 !strcasecmp(name, "cc_callback_macro") || 00733 !strcasecmp(name, "cc_agent_dialstring") || 00734 !strcasecmp(name, "cc_recall_timer")); 00735 }
int ast_cc_is_recall | ( | struct ast_channel * | chan, | |
int * | core_id, | |||
const char *const | monitor_type | |||
) |
Decide if a call to a particular channel is a CC recall.
As a quick example, let's say a call is placed to SIP/1000 and SIP/1000 is currently on the phone. The caller requests CCBS. SIP/1000 finishes his call, and so the caller attempts to recall. Now, the dialplan administrator has set up this second call so that not only is SIP/1000 called, but also SIP/2000 is called. If SIP/1000's channel were passed to this function, the return value would be non-zero, but if SIP/2000's channel were passed into this function, then the return would be 0 since SIP/2000 was not one of the original devices dialed.
This function will lock the channel as well as the list of monitors on the channel datastore, though the locks are not held at the same time. Be sure that you have no potential lock order issues here.
chan | The channel to check | |
[out] | core_id | If this is a valid CC recall, the core_id of the failed call will be placed in this output parameter |
monitor_type | Clarify which type of monitor type we are looking for if this is happening on a called channel. For incoming channels, this parameter is not used. |
0 | Either this is not a recall or it is but this channel is not part of the recall | |
non-zero | This is a recall and the channel in question is directly involved. |
Definition at line 3157 of file ccss.c.
References ast_assert, ast_channel_datastore_find(), ast_channel_get_device_name(), ast_channel_lock, AST_CHANNEL_NAME, ast_channel_unlock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), cc_recall_ds_data::core_id, ast_datastore::data, ast_cc_interface::device_name, cc_recall_ds_data::ignore, ast_cc_monitor::interface, cc_recall_ds_data::interface_tree, ast_cc_interface::monitor_type, cc_recall_ds_data::nested, cc_monitor_backend::next, and recall_ds_info.
Referenced by cc_core_init_instance(), sig_pri_call(), sip_call(), and wait_for_answer().
03158 { 03159 struct ast_datastore *recall_datastore; 03160 struct cc_recall_ds_data *recall_data; 03161 struct cc_monitor_tree *interface_tree; 03162 char device_name[AST_CHANNEL_NAME]; 03163 struct ast_cc_monitor *device_monitor; 03164 int core_id_candidate; 03165 03166 ast_assert(core_id != NULL); 03167 03168 *core_id = -1; 03169 03170 ast_channel_lock(chan); 03171 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03172 /* Obviously not a recall if the datastore isn't present */ 03173 ast_channel_unlock(chan); 03174 return 0; 03175 } 03176 03177 recall_data = recall_datastore->data; 03178 03179 if (recall_data->ignore) { 03180 /* Though this is a recall, the call to this particular interface is not part of the 03181 * recall either because this is a call forward or because this is not the first 03182 * invocation of Dial during this call 03183 */ 03184 ast_channel_unlock(chan); 03185 return 0; 03186 } 03187 03188 if (!recall_data->nested) { 03189 /* If the nested flag is not set, then this means that 03190 * the channel passed to this function is the caller making 03191 * the recall. This means that we shouldn't look through 03192 * the monitor tree for the channel because it shouldn't be 03193 * there. However, this is a recall though, so return true. 03194 */ 03195 *core_id = recall_data->core_id; 03196 ast_channel_unlock(chan); 03197 return 1; 03198 } 03199 03200 if (ast_strlen_zero(monitor_type)) { 03201 /* If someone passed a NULL or empty monitor type, then it is clear 03202 * the channel they passed in was an incoming channel, and so searching 03203 * the list of dialed interfaces is not going to be helpful. Just return 03204 * false immediately. 03205 */ 03206 ast_channel_unlock(chan); 03207 return 0; 03208 } 03209 03210 interface_tree = recall_data->interface_tree; 03211 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 03212 /* We grab the value of the recall_data->core_id so that we 03213 * can unlock the channel before we start looking through the 03214 * interface list. That way we don't have to worry about a possible 03215 * clash between the channel lock and the monitor tree lock. 03216 */ 03217 core_id_candidate = recall_data->core_id; 03218 ast_channel_unlock(chan); 03219 03220 /* 03221 * Now we need to find out if the channel device name 03222 * is in the list of interfaces in the called tree. 03223 */ 03224 AST_LIST_LOCK(interface_tree); 03225 AST_LIST_TRAVERSE(interface_tree, device_monitor, next) { 03226 if (!strcmp(device_monitor->interface->device_name, device_name) && 03227 !strcmp(device_monitor->interface->monitor_type, monitor_type)) { 03228 /* BOOM! Device is in the tree! We have a winner! */ 03229 *core_id = core_id_candidate; 03230 AST_LIST_UNLOCK(interface_tree); 03231 return 1; 03232 } 03233 } 03234 AST_LIST_UNLOCK(interface_tree); 03235 return 0; 03236 }
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 3517 of file ccss.c.
References CC_CALLEE_READY, and cc_request_state_change().
Referenced by cc_generic_monitor_destructor(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), generic_monitor_devstate_tp_cb(), handle_cc_notify(), and sig_pri_handle_cis_subcmds().
03518 { 03519 va_list ap; 03520 int res; 03521 03522 va_start(ap, debug); 03523 res = cc_request_state_change(CC_CALLEE_READY, core_id, debug, ap); 03524 va_end(ap); 03525 return res; 03526 }
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 4090 of file ccss.c.
References ao2_t_callback, ast_log_dynamic_level, cc_core_instances, count_monitors_cb_data::count, count_monitors_cb(), count_monitors_cb_data::device_name, and OBJ_NODATA.
Referenced by ast_queue_cc_frame().
04091 { 04092 struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,}; 04093 04094 ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents"); 04095 ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count); 04096 return data.count; 04097 }
int ast_cc_monitor_failed | ( | int | core_id, | |
const char *const | monitor_name, | |||
const char *const | debug, | |||
... | ||||
) |
Indicate that a failure has occurred on a specific monitor.
If there are no more devices left to monitor when this function is called, then the core will fail the CC transaction globally.
core_id | The core ID for the CC transaction | |
monitor_name | The name of the monitor on which the failure occurred | |
debug | A debug message to print to the CC log |
Definition at line 3663 of file ccss.c.
References ast_calloc, ast_free, ast_strdup, ast_taskprocessor_push(), ast_vasprintf, cc_core_taskprocessor, and cc_monitor_failed().
Referenced by ast_cc_available_timer_expire(), cc_handle_publish_error(), handle_response_subscribe(), sig_pri_cc_link_canceled(), and sig_pri_handle_cis_subcmds().
03664 { 03665 struct ast_cc_monitor_failure_data *failure_data; 03666 int res; 03667 va_list ap; 03668 03669 if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) { 03670 return -1; 03671 } 03672 03673 if (!(failure_data->device_name = ast_strdup(monitor_name))) { 03674 ast_free(failure_data); 03675 return -1; 03676 } 03677 03678 va_start(ap, debug); 03679 if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) { 03680 va_end(ap); 03681 ast_free((char *)failure_data->device_name); 03682 ast_free(failure_data); 03683 return -1; 03684 } 03685 va_end(ap); 03686 03687 failure_data->core_id = core_id; 03688 03689 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_monitor_failed, failure_data); 03690 if (res) { 03691 ast_free((char *)failure_data->device_name); 03692 ast_free((char *)failure_data->debug); 03693 ast_free(failure_data); 03694 } 03695 return res; 03696 }
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 3773 of file ccss.c.
References ast_taskprocessor_push(), cc_core_taskprocessor, cc_party_b_free(), cc_unref(), and find_cc_core_instance().
Referenced by sig_pri_handle_cis_subcmds().
03774 { 03775 int res; 03776 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03777 03778 if (!core_instance) { 03779 return -1; 03780 } 03781 03782 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_party_b_free, core_instance); 03783 if (res) { 03784 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03785 } 03786 return res; 03787 }
int ast_cc_monitor_register | ( | const struct ast_cc_monitor_callbacks * | callbacks | ) |
Register a set of monitor callbacks with the core.
callbacks | The callbacks used by the monitor implementation |
0 | Successfully registered | |
-1 | Failure to register |
Definition at line 891 of file ccss.c.
References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and cc_monitor_backend::next.
Referenced by ast_cc_init(), and load_module().
00892 { 00893 struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend)); 00894 00895 if (!backend) { 00896 return -1; 00897 } 00898 00899 backend->callbacks = callbacks; 00900 00901 AST_RWLIST_WRLOCK(&cc_monitor_backends); 00902 AST_RWLIST_INSERT_TAIL(&cc_monitor_backends, backend, next); 00903 AST_RWLIST_UNLOCK(&cc_monitor_backends); 00904 return 0; 00905 }
int ast_cc_monitor_request_acked | ( | int | core_id, | |
const char *const | debug, | |||
... | ||||
) |
Indicate that an outbound entity has accepted our CC request.
core_id | core_id of the CC transaction | |
debug | optional string to print for debugging purposes |
0 | Success | |
-1 | Failure |
Definition at line 3506 of file ccss.c.
References CC_ACTIVE, and cc_request_state_change().
Referenced by cc_generic_monitor_request_cc(), cc_stop_ringing(), handle_cc_notify(), and sig_pri_handle_cis_subcmds().
03507 { 03508 va_list ap; 03509 int res; 03510 03511 va_start(ap, debug); 03512 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap); 03513 va_end(ap); 03514 return res; 03515 }
int ast_cc_monitor_status_request | ( | int | core_id | ) |
Request the status of a caller or callers.
When an ISDN PTMP monitor senses that the callee has become available, it needs to know the current status of the caller in order to determine the appropriate response to send to the caller. In order to do this, the monitor calls this function. Responses will arrive asynchronously.
core_id | The core ID of the CC transaction |
0 | Successfully requested status | |
-1 | Failed to request status |
Definition at line 3708 of file ccss.c.
References ast_taskprocessor_push(), cc_core_taskprocessor, cc_status_request(), cc_unref(), and find_cc_core_instance().
Referenced by sig_pri_handle_cis_subcmds().
03709 { 03710 int res; 03711 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03712 03713 if (!core_instance) { 03714 return -1; 03715 } 03716 03717 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_request, core_instance); 03718 if (res) { 03719 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03720 } 03721 return res; 03722 }
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 3745 of file ccss.c.
References ast_taskprocessor_push(), cc_core_taskprocessor, cc_stop_ringing(), cc_unref(), and find_cc_core_instance().
Referenced by sig_pri_handle_cis_subcmds().
03746 { 03747 int res; 03748 struct cc_core_instance *core_instance = find_cc_core_instance(core_id); 03749 03750 if (!core_instance) { 03751 return -1; 03752 } 03753 03754 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_stop_ringing, core_instance); 03755 if (res) { 03756 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03757 } 03758 return res; 03759 }
void ast_cc_monitor_unregister | ( | const struct ast_cc_monitor_callbacks * | callbacks | ) |
Unregister a set of monitor callbacks with the core.
callbacks | The callbacks used by the monitor implementation |
0 | Successfully unregistered | |
-1 | Failure to unregister |
Definition at line 924 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().
00925 { 00926 struct cc_monitor_backend *backend; 00927 AST_RWLIST_WRLOCK(&cc_monitor_backends); 00928 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_monitor_backends, backend, next) { 00929 if (backend->callbacks == callbacks) { 00930 AST_RWLIST_REMOVE_CURRENT(next); 00931 ast_free(backend); 00932 break; 00933 } 00934 } 00935 AST_RWLIST_TRAVERSE_SAFE_END; 00936 AST_RWLIST_UNLOCK(&cc_monitor_backends); 00937 }
int ast_cc_offer | ( | struct ast_channel * | caller_chan | ) |
Offer CC to a caller.
caller_chan | The calling channel |
-1 | Error | |
0 | Success |
Definition at line 3470 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, cc_offer(), dialed_cc_interfaces::core_id, cc_recall_ds_data::core_id, ast_datastore::data, dialed_cc_interfaces_info, dialed_cc_interfaces::is_original_caller, and ast_channel::name.
Referenced by ast_hangup().
03471 { 03472 int core_id; 03473 int res = -1; 03474 struct ast_datastore *datastore; 03475 struct dialed_cc_interfaces *cc_interfaces; 03476 char cc_is_offerable; 03477 03478 ast_channel_lock(caller_chan); 03479 if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) { 03480 ast_channel_unlock(caller_chan); 03481 return res; 03482 } 03483 03484 cc_interfaces = datastore->data; 03485 cc_is_offerable = cc_interfaces->is_original_caller; 03486 core_id = cc_interfaces->core_id; 03487 ast_channel_unlock(caller_chan); 03488 03489 if (cc_is_offerable) { 03490 res = cc_offer(core_id, "CC offered to caller %s", caller_chan->name); 03491 } 03492 return res; 03493 }
int ast_cc_request_is_within_limits | ( | void | ) |
Check if the incoming CC request is within the bounds set by the cc_max_requests configuration option.
If this is not called and a state change to CC_CALLER_REQUESTED is made, then the core will still not allow for the request to succeed. However, if done this way, it may not be obvious to the requestor why the request failed.
0 | Not within the limits. Fail. | |
non-zero | Within the limits. Success. |
Definition at line 2209 of file ccss.c.
Referenced by cc_caller_requested(), cc_interfaces_datastore_init(), ccreq_exec(), and sig_pri_handle_cis_subcmds().
02210 { 02211 return cc_request_count < global_cc_max_requests; 02212 }
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 684 of file ccss.c.
References ast_log(), ast_set_cc_agent_dialstring(), ast_set_cc_agent_policy(), ast_set_cc_callback_macro(), ast_set_cc_max_agents(), ast_set_cc_max_monitors(), ast_set_cc_monitor_policy(), ast_set_cc_offer_timer(), ast_set_cc_recall_timer(), ast_set_ccbs_available_timer(), ast_set_ccnr_available_timer(), LOG_WARNING, str_to_agent_policy(), and str_to_monitor_policy().
Referenced by acf_cc_write(), and build_peer().
00686 { 00687 unsigned int value_as_uint; 00688 if (!strcasecmp(name, "cc_agent_policy")) { 00689 return ast_set_cc_agent_policy(params, str_to_agent_policy(value)); 00690 } else if (!strcasecmp(name, "cc_monitor_policy")) { 00691 return ast_set_cc_monitor_policy(params, str_to_monitor_policy(value)); 00692 } else if (!strcasecmp(name, "cc_agent_dialstring")) { 00693 ast_set_cc_agent_dialstring(params, value); 00694 } else if (!strcasecmp(name, "cc_callback_macro")) { 00695 ast_set_cc_callback_macro(params, value); 00696 return 0; 00697 } 00698 00699 if (!sscanf(value, "%30u", &value_as_uint) == 1) { 00700 return -1; 00701 } 00702 00703 if (!strcasecmp(name, "cc_offer_timer")) { 00704 ast_set_cc_offer_timer(params, value_as_uint); 00705 } else if (!strcasecmp(name, "ccnr_available_timer")) { 00706 ast_set_ccnr_available_timer(params, value_as_uint); 00707 } else if (!strcasecmp(name, "ccbs_available_timer")) { 00708 ast_set_ccbs_available_timer(params, value_as_uint); 00709 } else if (!strcasecmp(name, "cc_max_agents")) { 00710 ast_set_cc_max_agents(params, value_as_uint); 00711 } else if (!strcasecmp(name, "cc_max_monitors")) { 00712 ast_set_cc_max_monitors(params, value_as_uint); 00713 } else if (!strcasecmp(name, "cc_recall_timer")) { 00714 ast_set_cc_recall_timer(params, value_as_uint); 00715 } else { 00716 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name); 00717 return -1; 00718 } 00719 00720 return 0; 00721 }
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 836 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and generic_recall().
00837 { 00838 return config->cc_agent_dialstring; 00839 }
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 742 of file ccss.c.
References config.
Referenced by ast_cc_call_init(), ast_cc_get_param(), build_peer(), cc_core_init_instance(), and find_agent_callbacks().
00743 { 00744 return config->cc_agent_policy; 00745 }
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 870 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and generic_recall().
00871 { 00872 return config->cc_callback_macro; 00873 }
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 850 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and cc_core_init_instance().
00851 { 00852 return config->cc_max_agents; 00853 }
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 860 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and ast_queue_cc_frame().
00861 { 00862 return config->cc_max_monitors; 00863 }
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 759 of file ccss.c.
References config.
Referenced by analog_call(), ast_cc_call_failed(), ast_cc_get_param(), dahdi_cc_callback(), sig_pri_cc_available(), sig_pri_cc_generic_check(), and sip_handle_cc().
00760 { 00761 return config->cc_monitor_policy; 00762 }
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 776 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), cc_generic_agent_start_offer_timer(), and sip_cc_agent_start_offer_timer().
00777 { 00778 return config->cc_offer_timer; 00779 }
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 806 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), and generic_recall().
00807 { 00808 return config->cc_recall_timer; 00809 }
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 821 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().
00822 { 00823 return config->ccbs_available_timer; 00824 }
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 791 of file ccss.c.
References config.
Referenced by ast_cc_get_param(), cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().
00792 { 00793 return config->ccnr_available_timer; 00794 }
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 2038 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_CC, ast_indicate_data(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_log_dynamic_level, call_destructor_with_no_monitor(), cc_core_init_instance(), cc_device_monitor_init(), cc_extension_monitor_change_is_valid(), cc_ref(), cc_service_to_string(), cc_unref(), cc_core_instance::core_id, dialed_cc_interfaces::core_id, ast_datastore::data, cc_control_payload::device_name, dialed_cc_interfaces_info, cc_control_payload::dialstring, ast_cc_monitor::dialstring, EVENT_FLAG_CC, find_cc_core_instance(), dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, dialed_cc_interfaces::is_original_caller, LOG_WARNING, manager_event, monitor, cc_control_payload::monitor_type, cc_monitor_backend::next, cc_control_payload::private_data, and cc_control_payload::service.
Referenced by ast_cc_busy_interface(), and ast_cc_call_failed().
02039 { 02040 char *device_name; 02041 char *dialstring; 02042 struct ast_cc_monitor *monitor; 02043 struct ast_datastore *cc_datastore; 02044 struct dialed_cc_interfaces *cc_interfaces; 02045 struct cc_control_payload *cc_data = frame_data; 02046 struct cc_core_instance *core_instance; 02047 02048 device_name = cc_data->device_name; 02049 dialstring = cc_data->dialstring; 02050 02051 ast_channel_lock(inbound); 02052 if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) { 02053 ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name); 02054 ast_channel_unlock(inbound); 02055 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02056 return; 02057 } 02058 02059 cc_interfaces = cc_datastore->data; 02060 02061 if (cc_interfaces->ignore) { 02062 ast_channel_unlock(inbound); 02063 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02064 return; 02065 } 02066 02067 if (!cc_interfaces->is_original_caller) { 02068 /* If the is_original_caller is not set on the *inbound* channel, then 02069 * it must be a local channel. As such, we do not want to create a core instance 02070 * or an agent for the local channel. Instead, we want to pass this along to the 02071 * other side of the local channel so that the original caller can benefit. 02072 */ 02073 ast_channel_unlock(inbound); 02074 ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data)); 02075 return; 02076 } 02077 02078 core_instance = find_cc_core_instance(cc_interfaces->core_id); 02079 if (!core_instance) { 02080 core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree, 02081 cc_interfaces->core_id, cc_data); 02082 if (!core_instance) { 02083 cc_interfaces->ignore = 1; 02084 ast_channel_unlock(inbound); 02085 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02086 return; 02087 } 02088 } 02089 02090 ast_channel_unlock(inbound); 02091 02092 /* Yeah this kind of sucks, but luckily most people 02093 * aren't dialing thousands of interfaces on every call 02094 * 02095 * This traversal helps us to not create duplicate monitors in 02096 * case a device queues multiple CC control frames. 02097 */ 02098 AST_LIST_LOCK(cc_interfaces->interface_tree); 02099 AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) { 02100 if (!strcmp(monitor->interface->device_name, device_name)) { 02101 ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n", 02102 core_instance->core_id, device_name); 02103 AST_LIST_UNLOCK(cc_interfaces->interface_tree); 02104 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance"); 02105 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02106 return; 02107 } 02108 } 02109 AST_LIST_UNLOCK(cc_interfaces->interface_tree); 02110 02111 if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) { 02112 ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name); 02113 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance"); 02114 call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data); 02115 return; 02116 } 02117 02118 AST_LIST_LOCK(cc_interfaces->interface_tree); 02119 cc_ref(monitor, "monitor tree's reference to the monitor"); 02120 AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next); 02121 AST_LIST_UNLOCK(cc_interfaces->interface_tree); 02122 02123 cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0); 02124 02125 manager_event(EVENT_FLAG_CC, "CCAvailable", 02126 "CoreID: %d\r\n" 02127 "Callee: %s\r\n" 02128 "Service: %s\r\n", 02129 cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service) 02130 ); 02131 02132 cc_unref(core_instance, "Done with core_instance after handling CC control frame"); 02133 cc_unref(monitor, "Unref reference from allocating monitor"); 02134 }
void ast_ignore_cc | ( | struct ast_channel * | chan | ) |
Mark the channel to ignore further CC activity.
chan | The channel for which further CC processing should be ignored. |
void |
Definition at line 3439 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore::data, dialed_cc_interfaces_info, cc_recall_ds_data::ignore, dialed_cc_interfaces::ignore, and recall_ds_info.
Referenced by dial_exec_full(), and do_forward().
03440 { 03441 struct ast_datastore *cc_datastore; 03442 struct ast_datastore *cc_recall_datastore; 03443 struct dialed_cc_interfaces *cc_interfaces; 03444 struct cc_recall_ds_data *recall_cc_data; 03445 03446 ast_channel_lock(chan); 03447 if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) { 03448 cc_interfaces = cc_datastore->data; 03449 cc_interfaces->ignore = 1; 03450 } 03451 03452 if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03453 recall_cc_data = cc_recall_datastore->data; 03454 recall_cc_data->ignore = 1; 03455 } 03456 ast_channel_unlock(chan); 03457 }
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 3871 of file ccss.c.
References ast_cc_build_frame(), ast_cc_monitor_count(), ast_channel_get_cc_config_params(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_frfree, ast_get_cc_max_monitors(), ast_log(), ast_queue_frame(), and LOG_NOTICE.
Referenced by analog_call(), sig_pri_cc_available(), sig_pri_cc_generic_check(), and sip_handle_cc().
03873 { 03874 struct ast_frame frame = {0,}; 03875 char device_name[AST_CHANNEL_NAME]; 03876 int retval; 03877 struct ast_cc_config_params *cc_params; 03878 03879 cc_params = ast_channel_get_cc_config_params(chan); 03880 if (!cc_params) { 03881 return -1; 03882 } 03883 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 03884 if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) { 03885 ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name); 03886 return -1; 03887 } 03888 03889 if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) { 03890 /* Frame building failed. We can't use this. */ 03891 return -1; 03892 } 03893 retval = ast_queue_frame(chan, &frame); 03894 ast_frfree(&frame); 03895 return retval; 03896 }
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 841 of file ccss.c.
References ast_copy_string(), ast_strlen_zero(), and config.
Referenced by ast_cc_set_param().
00842 { 00843 if (ast_strlen_zero(value)) { 00844 config->cc_agent_dialstring[0] = '\0'; 00845 } else { 00846 ast_copy_string(config->cc_agent_dialstring, value, sizeof(config->cc_agent_dialstring)); 00847 } 00848 }
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 747 of file ccss.c.
References AST_CC_AGENT_GENERIC, and config.
Referenced by ast_cc_set_param(), and build_peer().
00748 { 00749 /* Screw C and its weak type checking for making me have to do this 00750 * validation at runtime. 00751 */ 00752 if (value < AST_CC_AGENT_NEVER || value > AST_CC_AGENT_GENERIC) { 00753 return -1; 00754 } 00755 config->cc_agent_policy = value; 00756 return 0; 00757 }
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 875 of file ccss.c.
References ast_copy_string(), ast_strlen_zero(), and config.
Referenced by ast_cc_set_param().
00876 { 00877 if (ast_strlen_zero(value)) { 00878 config->cc_callback_macro[0] = '\0'; 00879 } else { 00880 ast_copy_string(config->cc_callback_macro, value, sizeof(config->cc_callback_macro)); 00881 } 00882 }
int ast_set_cc_interfaces_chanvar | ( | struct ast_channel * | chan, | |
const char *const | extension | |||
) |
Set the CC_INTERFACES channel variable for a channel using an extension as a starting point.
chan | The channel to set the CC_INTERFACES variable on | |
extension | The name of the extension for which we're setting the variable. This should be in the form of "exten@context" |
Definition at line 3387 of file ccss.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_str_buffer(), ast_str_create(), build_cc_interfaces_chanvar(), cc_recall_ds_data::core_id, ast_datastore::data, ast_cc_interface::device_name, ast_cc_monitor::interface, cc_recall_ds_data::interface_tree, cc_monitor_backend::next, pbx_builtin_setvar_helper(), recall_ds_info, and str.
Referenced by local_call().
03388 { 03389 struct ast_datastore *recall_datastore; 03390 struct cc_monitor_tree *interface_tree; 03391 struct ast_cc_monitor *monitor_iter; 03392 struct cc_recall_ds_data *recall_data; 03393 struct ast_str *str = ast_str_create(64); 03394 int core_id; 03395 03396 if (!str) { 03397 return -1; 03398 } 03399 03400 ast_channel_lock(chan); 03401 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) { 03402 ast_channel_unlock(chan); 03403 ast_free(str); 03404 return -1; 03405 } 03406 recall_data = recall_datastore->data; 03407 interface_tree = recall_data->interface_tree; 03408 core_id = recall_data->core_id; 03409 ast_channel_unlock(chan); 03410 03411 AST_LIST_LOCK(interface_tree); 03412 AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) { 03413 if (!strcmp(monitor_iter->interface->device_name, extension)) { 03414 break; 03415 } 03416 } 03417 03418 if (!monitor_iter) { 03419 /* We couldn't find this extension. This may be because 03420 * we have been directed into an unexpected extension because 03421 * the admin has changed a CC_INTERFACES variable at some point. 03422 */ 03423 AST_LIST_UNLOCK(interface_tree); 03424 ast_free(str); 03425 return -1; 03426 } 03427 03428 build_cc_interfaces_chanvar(monitor_iter, str); 03429 AST_LIST_UNLOCK(interface_tree); 03430 03431 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str)); 03432 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n", 03433 core_id, ast_str_buffer(str)); 03434 03435 ast_free(str); 03436 return 0; 03437 }
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 855 of file ccss.c.
References config.
Referenced by ast_cc_set_param().
void ast_set_cc_max_monitors | ( | struct ast_cc_config_params * | config, | |
unsigned int | value | |||
) |
Set the cc_max_monitors.
config | The configuration to set the cc_max_monitors on | |
value | The new cc_max_monitors we want to change to |
void |
Definition at line 865 of file ccss.c.
References config.
Referenced by ast_cc_set_param().
int ast_set_cc_monitor_policy | ( | struct ast_cc_config_params * | config, | |
enum ast_cc_monitor_policies | value | |||
) |
Set the cc_monitor_policy.
config | The configuration to set the cc_monitor_policy on | |
value | The new cc_monitor_policy we want to change to |
0 | Success | |
-1 | Failure (likely due to bad input) |
Definition at line 764 of file ccss.c.
References AST_CC_MONITOR_ALWAYS, and config.
Referenced by ast_cc_set_param().
00765 { 00766 /* Screw C and its weak type checking for making me have to do this 00767 * validation at runtime. 00768 */ 00769 if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) { 00770 return -1; 00771 } 00772 config->cc_monitor_policy = value; 00773 return 0; 00774 }
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 781 of file ccss.c.
References ast_log(), config, and LOG_WARNING.
Referenced by ast_cc_set_param().
00782 { 00783 /* 0 is an unreasonable value for any timer. Stick with the default */ 00784 if (value == 0) { 00785 ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer); 00786 return; 00787 } 00788 config->cc_offer_timer = value; 00789 }
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 811 of file ccss.c.
References ast_log(), config, and LOG_WARNING.
Referenced by ast_cc_set_param().
00812 { 00813 /* 0 is an unreasonable value for any timer. Stick with the default */ 00814 if (value == 0) { 00815 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->cc_recall_timer); 00816 return; 00817 } 00818 config->cc_recall_timer = value; 00819 }
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 826 of file ccss.c.
References ast_log(), config, and LOG_WARNING.
Referenced by ast_cc_set_param().
00827 { 00828 /* 0 is an unreasonable value for any timer. Stick with the default */ 00829 if (value == 0) { 00830 ast_log(LOG_WARNING, "0 is an invalid value for ccbs_available_timer. Retaining value as %u\n", config->ccbs_available_timer); 00831 return; 00832 } 00833 config->ccbs_available_timer = value; 00834 }
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 796 of file ccss.c.
References ast_log(), config, and LOG_WARNING.
Referenced by ast_cc_set_param().
00797 { 00798 /* 0 is an unreasonable value for any timer. Stick with the default */ 00799 if (value == 0) { 00800 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->ccnr_available_timer); 00801 return; 00802 } 00803 config->ccnr_available_timer = value; 00804 }
int ast_setup_cc_recall_datastore | ( | struct ast_channel * | chan, | |
const int | core_id | |||
) |
Set up a CC recall datastore on a channel.
This function must be called by the implementer once it has been detected that an inbound call is a cc_recall. After allocating the channel, call this function, followed by ast_cc_set_cc_interfaces_chanvar. While it would be nice to be able to have the core do this automatically, it just cannot be done given the current architecture.
Definition at line 3124 of file ccss.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_free, cc_ref(), cc_unref(), ast_datastore::data, DATASTORE_INHERIT_FOREVER, find_cc_core_instance(), ast_datastore::inheritance, cc_core_instance::monitors, and recall_ds_info.
Referenced by generic_recall(), handle_request_invite(), and sig_pri_handle_subcmds().
03125 { 03126 struct ast_datastore *recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL); 03127 struct cc_recall_ds_data *recall_data; 03128 struct cc_core_instance *core_instance; 03129 03130 if (!recall_datastore) { 03131 return -1; 03132 } 03133 03134 if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) { 03135 ast_datastore_free(recall_datastore); 03136 return -1; 03137 } 03138 03139 if (!(core_instance = find_cc_core_instance(core_id))) { 03140 ast_free(recall_data); 03141 ast_datastore_free(recall_datastore); 03142 return -1; 03143 } 03144 03145 recall_data->interface_tree = cc_ref(core_instance->monitors, 03146 "Bump refcount for monitor tree for recall datastore"); 03147 recall_data->core_id = core_id; 03148 recall_datastore->data = recall_data; 03149 recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER; 03150 ast_channel_lock(chan); 03151 ast_channel_datastore_add(chan, recall_datastore); 03152 ast_channel_unlock(chan); 03153 cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref"); 03154 return 0; 03155 }
static void build_cc_interfaces_chanvar | ( | struct ast_cc_monitor * | starting_point, | |
struct ast_str * | str | |||
) | [static] |
Definition at line 3307 of file ccss.c.
References AST_LIST_NEXT, AST_LIST_TRAVERSE, ast_log(), ast_str_strlen(), ast_str_truncate(), cc_unique_append(), extension_monitor_pvt::child_dialstrings, ast_cc_interface::device_name, ast_cc_monitor::dialstring, ast_cc_monitor::id, ast_cc_monitor::interface, extension_child_dialstring::is_valid, LOG_ERROR, cc_monitor_backend::next, extension_child_dialstring::original_dialstring, ast_cc_monitor::parent_id, ast_cc_monitor::private_data, and str.
Referenced by ast_cc_agent_set_interfaces_chanvar(), and ast_set_cc_interfaces_chanvar().
03308 { 03309 struct extension_monitor_pvt *extension_pvt; 03310 struct extension_child_dialstring *child_dialstring; 03311 struct ast_cc_monitor *monitor_iter = starting_point; 03312 int top_level_id = starting_point->id; 03313 size_t length; 03314 03315 /* Init to an empty string. */ 03316 ast_str_truncate(str, 0); 03317 03318 /* First we need to take all of the is_valid child_dialstrings from 03319 * the extension monitor we found and add them to the CC_INTERFACES 03320 * chanvar 03321 */ 03322 extension_pvt = starting_point->private_data; 03323 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) { 03324 if (child_dialstring->is_valid) { 03325 cc_unique_append(str, child_dialstring->original_dialstring); 03326 } 03327 } 03328 03329 /* And now we get the dialstrings from each of the device monitors */ 03330 while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) { 03331 if (monitor_iter->parent_id == top_level_id) { 03332 cc_unique_append(str, monitor_iter->dialstring); 03333 } 03334 } 03335 03336 /* str will have an extra '&' tacked onto the end of it, so we need 03337 * to get rid of that. 03338 */ 03339 length = ast_str_strlen(str); 03340 if (length) { 03341 ast_str_truncate(str, length - 1); 03342 } 03343 if (length <= 1) { 03344 /* Nothing to recall? This should not happen. */ 03345 ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n", 03346 starting_point->interface->device_name); 03347 } 03348 }
static void call_destructor_with_no_monitor | ( | const char *const | monitor_type, | |
void * | private_data | |||
) | [static] |
Definition at line 1936 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().
01937 { 01938 const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type); 01939 01940 if (!monitor_callbacks) { 01941 return; 01942 } 01943 01944 monitor_callbacks->destructor(private_data); 01945 }
static void cancel_available_timer | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2940 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, and cc_monitor_backend::next.
Referenced by cc_recalling().
02941 { 02942 struct ast_cc_monitor *monitor_iter; 02943 AST_LIST_LOCK(core_instance->monitors); 02944 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02945 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02946 if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) { 02947 AST_LIST_REMOVE_CURRENT(next); 02948 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02949 monitor_iter->interface->device_name, 1); 02950 cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor"); 02951 } 02952 } 02953 } 02954 AST_LIST_TRAVERSE_SAFE_END; 02955 02956 if (!has_device_monitors(core_instance)) { 02957 ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers"); 02958 } 02959 AST_LIST_UNLOCK(core_instance->monitors); 02960 }
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 2873 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().
02874 { 02875 /* Either 02876 * 1. Callee accepted CC request, call agent's ack callback. 02877 * 2. Caller became available, call agent's stop_monitoring callback and 02878 * call monitor's unsuspend callback. 02879 */ 02880 if (previous_state == CC_CALLER_REQUESTED) { 02881 core_instance->agent->callbacks->respond(core_instance->agent, 02882 AST_CC_AGENT_RESPONSE_SUCCESS); 02883 manager_event(EVENT_FLAG_CC, "CCRequestAcknowledged", 02884 "CoreID: %d\r\n" 02885 "Caller: %s\r\n", 02886 core_instance->core_id, core_instance->agent->device_name); 02887 } else if (previous_state == CC_CALLER_BUSY) { 02888 manager_event(EVENT_FLAG_CC, "CCCallerStopMonitoring", 02889 "CoreID: %d\r\n" 02890 "Caller: %s\r\n", 02891 core_instance->core_id, core_instance->agent->device_name); 02892 unsuspend(core_instance); 02893 } 02894 /* Not possible for previous_state to be anything else due to the is_state_change_valid check at the beginning */ 02895 return 0; 02896 }
static int cc_agent_callback_helper | ( | void * | obj, | |
void * | args, | |||
int | flags | |||
) | [static] |
Definition at line 430 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().
00431 { 00432 struct cc_core_instance *core_instance = obj; 00433 struct cc_callback_helper *helper = args; 00434 00435 if (strcmp(core_instance->agent->callbacks->type, helper->type)) { 00436 return 0; 00437 } 00438 00439 return helper->function(core_instance->agent, helper->args, flags); 00440 }
static struct ast_cc_agent* cc_agent_init | ( | struct ast_channel * | caller_chan, | |
const char *const | caller_name, | |||
const int | core_id, | |||
struct cc_monitor_tree * | interface_tree | |||
) | [static] |
Definition at line 2281 of file ccss.c.
References agent_destroy(), ao2_t_alloc, ast_cc_config_params_init, ast_cc_copy_config_params(), ast_channel_get_cc_config_params(), ast_log_dynamic_level, cc_unref(), check_callback_sanity(), ast_cc_agent::core_id, and find_agent_callbacks().
Referenced by cc_core_init_instance().
02284 { 02285 struct ast_cc_agent *agent; 02286 struct ast_cc_config_params *cc_params; 02287 02288 if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy, 02289 "Allocating new ast_cc_agent"))) { 02290 return NULL; 02291 } 02292 02293 agent->core_id = core_id; 02294 strcpy(agent->device_name, caller_name); 02295 02296 cc_params = ast_channel_get_cc_config_params(caller_chan); 02297 if (!cc_params) { 02298 cc_unref(agent, "Could not get channel config params."); 02299 return NULL; 02300 } 02301 if (!(agent->cc_params = ast_cc_config_params_init())) { 02302 cc_unref(agent, "Could not init agent config params."); 02303 return NULL; 02304 } 02305 ast_cc_copy_config_params(agent->cc_params, cc_params); 02306 02307 if (!(agent->callbacks = find_agent_callbacks(caller_chan))) { 02308 cc_unref(agent, "Could not find agent callbacks."); 02309 return NULL; 02310 } 02311 check_callback_sanity(agent->callbacks); 02312 02313 if (agent->callbacks->init(agent, caller_chan)) { 02314 cc_unref(agent, "Agent init callback failed."); 02315 return NULL; 02316 } 02317 ast_log_dynamic_level(cc_logger_level, "Core %d: Created an agent for caller %s\n", 02318 agent->core_id, agent->device_name); 02319 return agent; 02320 }
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 2754 of file ccss.c.
References ast_log(), and LOG_WARNING.
02755 { 02756 /* This should never happen... */ 02757 ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n"); 02758 return -1; 02759 }
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 3843 of file ccss.c.
References ast_cc_copy_config_params(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), cc_control_payload::config_params, ast_datastore::data, cc_control_payload::device_name, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces_info, cc_control_payload::dialstring, cc_control_payload::monitor_type, cc_control_payload::parent_interface_id, cc_control_payload::private_data, and cc_control_payload::service.
Referenced by ast_cc_build_frame(), ast_cc_busy_interface(), and ast_cc_call_failed().
03846 { 03847 struct ast_datastore *datastore; 03848 struct dialed_cc_interfaces *cc_interfaces; 03849 int dial_parent_id; 03850 03851 ast_channel_lock(chan); 03852 datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL); 03853 if (!datastore) { 03854 ast_channel_unlock(chan); 03855 return -1; 03856 } 03857 cc_interfaces = datastore->data; 03858 dial_parent_id = cc_interfaces->dial_parent_id; 03859 ast_channel_unlock(chan); 03860 03861 payload->monitor_type = monitor_type; 03862 payload->private_data = private_data; 03863 payload->service = service; 03864 ast_cc_copy_config_params(&payload->config_params, cc_params); 03865 payload->parent_interface_id = dial_parent_id; 03866 ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name)); 03867 ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring)); 03868 return 0; 03869 }
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 2898 of file ccss.c.
References cc_core_instance::agent, ast_cc_agent::callbacks, and ast_cc_agent_callbacks::callee_available.
02899 { 02900 core_instance->agent->callbacks->callee_available(core_instance->agent); 02901 return 0; 02902 }
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 2926 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().
02927 { 02928 /* Callee was available, but caller was busy, call agent's begin_monitoring callback 02929 * and call monitor's suspend callback. 02930 */ 02931 suspend(core_instance); 02932 core_instance->agent->callbacks->start_monitoring(core_instance->agent); 02933 manager_event(EVENT_FLAG_CC, "CCCallerStartMonitoring", 02934 "CoreID: %d\r\n" 02935 "Caller: %s\r\n", 02936 core_instance->core_id, core_instance->agent->device_name); 02937 return 0; 02938 }
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 2761 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.
02762 { 02763 if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) { 02764 ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n", 02765 core_instance->agent->device_name); 02766 return -1; 02767 } 02768 manager_event(EVENT_FLAG_CC, "CCOfferTimerStart", 02769 "CoreID: %d\r\n" 02770 "Caller: %s\r\n" 02771 "Expires: %u\r\n", 02772 core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer); 02773 ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n", 02774 core_instance->core_id, core_instance->agent->device_name); 02775 return 0; 02776 }
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 2837 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.
02838 { 02839 if (!ast_cc_request_is_within_limits()) { 02840 ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n"); 02841 core_instance->agent->callbacks->respond(core_instance->agent, 02842 AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY); 02843 ast_cc_failed(core_instance->core_id, "Too many requests in the system"); 02844 return -1; 02845 } 02846 core_instance->agent->callbacks->stop_offer_timer(core_instance->agent); 02847 request_cc(core_instance); 02848 return 0; 02849 }
static int cc_cli_output_status | ( | void * | data | ) | [static] |
Definition at line 4163 of file ccss.c.
References ao2_container_count(), ao2_t_callback, ast_cli(), ast_free, cc_core_instances, OBJ_NODATA, and print_stats_cb().
Referenced by handle_cc_status().
04164 { 04165 int *cli_fd = data; 04166 int count = ao2_container_count(cc_core_instances); 04167 04168 if (!count) { 04169 ast_cli(*cli_fd, "There are currently no active call completion transactions\n"); 04170 } else { 04171 ast_cli(*cli_fd, "%d Call completion transactions\n", count); 04172 ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n"); 04173 ast_cli(*cli_fd, "----------------------------------------------------------------------------\n"); 04174 ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI"); 04175 } 04176 ast_free(cli_fd); 04177 return 0; 04178 }
static void cc_cli_print_monitor_stats | ( | struct ast_cc_monitor * | monitor, | |
int | fd, | |||
int | parent_id | |||
) | [static] |
Definition at line 4130 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cli(), AST_LIST_NEXT, cc_service_to_string(), ast_cc_monitor::id, monitor, cc_monitor_backend::next, and ast_cc_monitor::parent_id.
Referenced by print_stats_cb().
04131 { 04132 struct ast_cc_monitor *child_monitor_iter = monitor; 04133 if (!monitor) { 04134 return; 04135 } 04136 04137 ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name); 04138 if (monitor->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 04139 ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered)); 04140 } 04141 ast_cli(fd, "\n"); 04142 04143 while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) { 04144 if (child_monitor_iter->parent_id == monitor->id) { 04145 cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id); 04146 } 04147 } 04148 }
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 2974 of file ccss.c.
References cc_core_instance::agent, ao2_t_unlink, cc_core_instances, cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, and manager_event.
02975 { 02976 /* Recall has made progress, call agent and monitor destructor functions 02977 */ 02978 manager_event(EVENT_FLAG_CC, "CCRecallComplete", 02979 "CoreID: %d\r\n" 02980 "Caller: %s\r\n", 02981 core_instance->core_id, core_instance->agent->device_name); 02982 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed"); 02983 return 0; 02984 }
static struct cc_core_instance * cc_core_init_instance | ( | struct ast_channel * | caller_chan, | |
struct cc_monitor_tree * | called_tree, | |||
const int | core_id, | |||
struct cc_control_payload * | cc_data | |||
) | [static] |
Definition at line 2637 of file ccss.c.
References ao2_t_alloc, ao2_t_link, AST_CC_AGENT_GENERIC, ast_cc_is_recall(), ast_channel_get_cc_config_params(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_get_cc_agent_policy(), ast_get_cc_max_agents(), ast_log_dynamic_level, cc_agent_init(), cc_core_instance_destructor(), cc_core_instances, cc_ref(), cc_unref(), count_agents(), and kill_duplicate_offers().
Referenced by ast_handle_cc_control_frame().
02639 { 02640 char caller[AST_CHANNEL_NAME]; 02641 struct cc_core_instance *core_instance; 02642 struct ast_cc_config_params *cc_params; 02643 long agent_count; 02644 int recall_core_id; 02645 02646 ast_channel_get_device_name(caller_chan, caller, sizeof(caller)); 02647 cc_params = ast_channel_get_cc_config_params(caller_chan); 02648 if (!cc_params) { 02649 ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n", 02650 caller); 02651 return NULL; 02652 } 02653 /* First, we need to kill off other pending CC offers from caller. If the caller is going 02654 * to request a CC service, it may only be for the latest call he made. 02655 */ 02656 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) { 02657 kill_duplicate_offers(caller); 02658 } 02659 02660 ast_cc_is_recall(caller_chan, &recall_core_id, NULL); 02661 agent_count = count_agents(caller, recall_core_id); 02662 if (agent_count >= ast_get_cc_max_agents(cc_params)) { 02663 ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller); 02664 return NULL; 02665 } 02666 02667 /* Generic agents can only have a single outstanding CC request per caller. */ 02668 if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) { 02669 ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n"); 02670 return NULL; 02671 } 02672 02673 /* Next, we need to create the core instance for this call */ 02674 if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) { 02675 return NULL; 02676 } 02677 02678 core_instance->core_id = core_id; 02679 if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) { 02680 cc_unref(core_instance, "Couldn't allocate agent, unref core_instance"); 02681 return NULL; 02682 } 02683 02684 core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree"); 02685 02686 ao2_t_link(cc_core_instances, core_instance, "Link core instance into container"); 02687 02688 return core_instance; 02689 }
static int cc_core_instance_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 409 of file ccss.c.
References CMP_MATCH, CMP_STOP, and cc_core_instance::core_id.
Referenced by ast_cc_init().
00410 { 00411 struct cc_core_instance *core_instance1 = obj; 00412 struct cc_core_instance *core_instance2 = arg; 00413 00414 return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0; 00415 }
static void cc_core_instance_destructor | ( | void * | data | ) | [static] |
Definition at line 2625 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().
02626 { 02627 struct cc_core_instance *core_instance = data; 02628 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id); 02629 if (core_instance->agent) { 02630 cc_unref(core_instance->agent, "Core instance is done with the agent now"); 02631 } 02632 if (core_instance->monitors) { 02633 core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list"); 02634 } 02635 }
static int cc_core_instance_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 403 of file ccss.c.
References cc_core_instance::core_id.
Referenced by ast_cc_init().
00404 { 00405 const struct cc_core_instance *core_instance = obj; 00406 return core_instance->core_id; 00407 }
static struct ast_cc_monitor* cc_device_monitor_init | ( | const char *const | device_name, | |
const char *const | dialstring, | |||
const struct cc_control_payload * | cc_data, | |||
int | core_id | |||
) | [static] |
Definition at line 1972 of file ccss.c.
References ao2_t_alloc, ast_atomic_fetchadd_int(), ast_cc_config_params_init, ast_cc_copy_config_params(), AST_CC_DEVICE_MONITOR, ast_log_dynamic_level, ast_strdup, cc_interface_destroy(), cc_monitor_destroy(), cc_unref(), cc_control_payload::config_params, find_monitor_callbacks(), monitor, cc_control_payload::monitor_type, ast_cc_monitor::parent_id, cc_control_payload::parent_interface_id, cc_control_payload::private_data, and cc_control_payload::service.
Referenced by ast_handle_cc_control_frame().
01973 { 01974 struct ast_cc_interface *cc_interface; 01975 struct ast_cc_monitor *monitor; 01976 size_t device_name_len = strlen(device_name); 01977 int parent_id = cc_data->parent_interface_id; 01978 01979 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy, 01980 "Allocating new ast_cc_interface"))) { 01981 return NULL; 01982 } 01983 01984 if (!(cc_interface->config_params = ast_cc_config_params_init())) { 01985 cc_unref(cc_interface, "Failed to allocate config params, unref interface"); 01986 return NULL; 01987 } 01988 01989 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) { 01990 cc_unref(cc_interface, "Failed to allocate monitor, unref interface"); 01991 return NULL; 01992 } 01993 01994 if (!(monitor->dialstring = ast_strdup(dialstring))) { 01995 cc_unref(monitor, "Failed to copy dialable name. Unref monitor"); 01996 cc_unref(cc_interface, "Failed to copy dialable name"); 01997 return NULL; 01998 } 01999 02000 if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) { 02001 cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor"); 02002 cc_unref(cc_interface, "Failed to find monitor callbacks"); 02003 return NULL; 02004 } 02005 02006 strcpy(cc_interface->device_name, device_name); 02007 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1); 02008 monitor->parent_id = parent_id; 02009 monitor->core_id = core_id; 02010 monitor->service_offered = cc_data->service; 02011 monitor->private_data = cc_data->private_data; 02012 cc_interface->monitor_type = cc_data->monitor_type; 02013 cc_interface->monitor_class = AST_CC_DEVICE_MONITOR; 02014 monitor->interface = cc_interface; 02015 monitor->available_timer_id = -1; 02016 ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params); 02017 ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %d and parent %d\n", 02018 monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id); 02019 return monitor; 02020 }
static int cc_do_state_change | ( | void * | datap | ) | [static] |
Definition at line 3009 of file ccss.c.
References cc_core_instance::agent, args, AST_CC_AGENT_RESPONSE_FAILURE_INVALID, ast_free, ast_log_dynamic_level, ast_cc_agent::callbacks, CC_CALLER_REQUESTED, cc_state_to_string(), cc_unref(), cc_core_instance::current_state, is_state_change_valid(), ast_cc_agent_callbacks::respond, and state_change_funcs.
Referenced by cc_request_state_change().
03010 { 03011 struct cc_state_change_args *args = datap; 03012 struct cc_core_instance *core_instance; 03013 enum cc_state previous_state; 03014 int res; 03015 03016 ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %d requested. Reason: %s\n", 03017 args->core_id, args->state, args->debug); 03018 03019 core_instance = args->core_instance; 03020 03021 if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) { 03022 ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n", 03023 args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state)); 03024 if (args->state == CC_CALLER_REQUESTED) { 03025 /* 03026 * For out-of-order requests, we need to let the requester know that 03027 * we can't handle the request now. 03028 */ 03029 core_instance->agent->callbacks->respond(core_instance->agent, 03030 AST_CC_AGENT_RESPONSE_FAILURE_INVALID); 03031 } 03032 ast_free(args); 03033 cc_unref(core_instance, "Unref core instance from when it was found earlier"); 03034 return -1; 03035 } 03036 03037 /* We can change to the new state now. */ 03038 previous_state = core_instance->current_state; 03039 core_instance->current_state = args->state; 03040 res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state); 03041 03042 ast_free(args); 03043 cc_unref(core_instance, "Unref since state change has completed"); /* From ao2_find */ 03044 return res; 03045 }
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 1770 of file ccss.c.
References AST_LIST_TRAVERSE, extension_monitor_pvt::child_dialstrings, extension_child_dialstring::device_name, ast_cc_monitor::id, extension_child_dialstring::is_valid, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor::private_data.
Referenced by ast_handle_cc_control_frame(), cancel_available_timer(), cc_monitor_failed(), request_cc(), suspend(), and unsuspend().
01771 { 01772 struct ast_cc_monitor *monitor_iter; 01773 struct extension_monitor_pvt *extension_pvt; 01774 struct extension_child_dialstring *child_dialstring; 01775 01776 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 01777 if (monitor_iter->id == parent_id) { 01778 break; 01779 } 01780 } 01781 01782 if (!monitor_iter) { 01783 return; 01784 } 01785 extension_pvt = monitor_iter->private_data; 01786 01787 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) { 01788 if (!strcmp(child_dialstring->device_name, device_name)) { 01789 child_dialstring->is_valid = is_valid; 01790 break; 01791 } 01792 } 01793 }
static void cc_extension_monitor_destructor | ( | void * | private_data | ) | [static] |
Definition at line 1541 of file ccss.c.
References ast_free, AST_LIST_REMOVE_HEAD, extension_monitor_pvt::child_dialstrings, and cc_monitor_backend::next.
Referenced by cc_monitor_destroy().
01542 { 01543 struct extension_monitor_pvt *extension_pvt = private_data; 01544 struct extension_child_dialstring *child_dialstring; 01545 01546 /* This shouldn't be possible, but I'm paranoid */ 01547 if (!extension_pvt) { 01548 return; 01549 } 01550 01551 while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) { 01552 ast_free(child_dialstring); 01553 } 01554 ast_free(extension_pvt); 01555 }
static struct ast_cc_monitor* cc_extension_monitor_init | ( | const char *const | exten, | |
const char *const | context, | |||
const unsigned int | parent_id | |||
) | [static] |
Definition at line 1809 of file ccss.c.
References ao2_t_alloc, ast_atomic_fetchadd_int(), AST_CC_EXTENSION_MONITOR, ast_log_dynamic_level, AST_MAX_EXTENSION, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_str_strlen(), cc_interface_destroy(), cc_monitor_destroy(), cc_unref(), extension_monitor_pvt_init(), monitor, and str.
Referenced by ast_cc_call_init(), and cc_interfaces_datastore_init().
01810 { 01811 struct ast_str *str = ast_str_alloca(2 * AST_MAX_EXTENSION); 01812 struct ast_cc_interface *cc_interface; 01813 struct ast_cc_monitor *monitor; 01814 01815 ast_str_set(&str, 0, "%s@%s", exten, context); 01816 01817 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy, 01818 "Allocating new ast_cc_interface"))) { 01819 return NULL; 01820 } 01821 01822 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) { 01823 cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface"); 01824 return NULL; 01825 } 01826 01827 if (!(monitor->private_data = extension_monitor_pvt_init())) { 01828 cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor"); 01829 cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface"); 01830 } 01831 01832 monitor->id = ast_atomic_fetchadd_int(&dialed_cc_interface_counter, +1); 01833 monitor->parent_id = parent_id; 01834 cc_interface->monitor_type = "extension"; 01835 cc_interface->monitor_class = AST_CC_EXTENSION_MONITOR; 01836 strcpy(cc_interface->device_name, ast_str_buffer(str)); 01837 monitor->interface = cc_interface; 01838 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); 01839 return monitor; 01840 }
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 2986 of file ccss.c.
References cc_core_instance::agent, ao2_t_unlink, args, cc_core_instances, cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, and manager_event.
02987 { 02988 manager_event(EVENT_FLAG_CC, "CCFailure", 02989 "CoreID: %d\r\n" 02990 "Caller: %s\r\n" 02991 "Reason: %s\r\n", 02992 core_instance->core_id, core_instance->agent->device_name, args->debug); 02993 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed"); 02994 return 0; 02995 }
static void cc_generic_agent_destructor | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2608 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.
02609 { 02610 struct cc_generic_agent_pvt *agent_pvt = agent->private_data; 02611 02612 if (!agent_pvt) { 02613 /* The agent constructor probably failed. */ 02614 return; 02615 } 02616 02617 cc_generic_agent_stop_offer_timer(agent); 02618 if (agent_pvt->sub) { 02619 agent_pvt->sub = ast_event_unsubscribe(agent_pvt->sub); 02620 } 02621 02622 ast_free(agent_pvt); 02623 }
static int cc_generic_agent_init | ( | struct ast_cc_agent * | agent, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 2396 of file ccss.c.
References ast_calloc, AST_CC_AGENT_SKIP_OFFER, ast_copy_string(), ast_set_flag, ast_channel::caller, ast_channel::context, ast_channel::exten, ast_party_caller::id, ast_channel::macrocontext, ast_channel::macroexten, ast_party_id::name, ast_party_id::number, ast_cc_agent::private_data, S_OR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
02397 { 02398 struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt)); 02399 02400 if (!generic_pvt) { 02401 return -1; 02402 } 02403 02404 generic_pvt->offer_timer_id = -1; 02405 if (chan->caller.id.number.valid && chan->caller.id.number.str) { 02406 ast_copy_string(generic_pvt->cid_num, chan->caller.id.number.str, sizeof(generic_pvt->cid_num)); 02407 } 02408 if (chan->caller.id.name.valid && chan->caller.id.name.str) { 02409 ast_copy_string(generic_pvt->cid_name, chan->caller.id.name.str, sizeof(generic_pvt->cid_name)); 02410 } 02411 ast_copy_string(generic_pvt->exten, S_OR(chan->macroexten, chan->exten), sizeof(generic_pvt->exten)); 02412 ast_copy_string(generic_pvt->context, S_OR(chan->macrocontext, chan->context), sizeof(generic_pvt->context)); 02413 agent->private_data = generic_pvt; 02414 ast_set_flag(agent, AST_CC_AGENT_SKIP_OFFER); 02415 return 0; 02416 }
static int cc_generic_agent_recall | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2592 of file ccss.c.
References ast_cc_agent_caller_busy(), ast_device_state(), ast_pthread_create_detached_background, cc_generic_is_device_available(), ast_cc_agent::core_id, ast_cc_agent::device_name, and generic_recall().
02593 { 02594 pthread_t clotho; 02595 enum ast_device_state current_state = ast_device_state(agent->device_name); 02596 02597 if (!cc_generic_is_device_available(current_state)) { 02598 /* We can't try to contact the device right now because he's not available 02599 * Let the core know he's busy. 02600 */ 02601 ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name); 02602 return 0; 02603 } 02604 ast_pthread_create_detached_background(&clotho, NULL, generic_recall, agent); 02605 return 0; 02606 }
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 2519 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.
02520 { 02521 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02522 struct ast_str *str = ast_str_alloca(128); 02523 02524 ast_assert(generic_pvt->sub == NULL); 02525 ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n", 02526 agent->device_name); 02527 02528 if (!(generic_pvt->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, 02529 generic_agent_devstate_cb, ast_str_buffer(str), agent, 02530 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, agent->device_name, 02531 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_EXISTS, 02532 AST_EVENT_IE_END))) { 02533 return -1; 02534 } 02535 return 0; 02536 }
static int cc_generic_agent_start_offer_timer | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2430 of file ccss.c.
References ast_assert, ast_get_cc_offer_timer(), ast_log_dynamic_level, ast_sched_thread_add(), ast_cc_agent::cc_params, cc_ref(), cc_sched_thread, ast_cc_agent::core_id, offer_timer_expire(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.
02431 { 02432 int when; 02433 int sched_id; 02434 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02435 02436 ast_assert(cc_sched_thread != NULL); 02437 ast_assert(agent->cc_params != NULL); 02438 02439 when = ast_get_cc_offer_timer(agent->cc_params) * 1000; 02440 ast_log_dynamic_level(cc_logger_level, "Core %d: About to schedule offer timer expiration for %d ms\n", 02441 agent->core_id, when); 02442 if ((sched_id = ast_sched_thread_add(cc_sched_thread, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) { 02443 return -1; 02444 } 02445 generic_pvt->offer_timer_id = sched_id; 02446 return 0; 02447 }
static int cc_generic_agent_status_request | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2470 of file ccss.c.
References ast_cc_agent_status_response(), ast_device_state(), ast_cc_agent::core_id, and ast_cc_agent::device_name.
02471 { 02472 ast_cc_agent_status_response(agent->core_id, ast_device_state(agent->device_name)); 02473 return 0; 02474 }
static int cc_generic_agent_stop_offer_timer | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2449 of file ccss.c.
References ast_sched_thread_del, cc_sched_thread, cc_unref(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.
Referenced by cc_generic_agent_destructor().
02450 { 02451 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02452 02453 if (generic_pvt->offer_timer_id != -1) { 02454 if (!ast_sched_thread_del(cc_sched_thread, generic_pvt->offer_timer_id)) { 02455 cc_unref(agent, "Remove scheduler's reference to the agent"); 02456 } 02457 generic_pvt->offer_timer_id = -1; 02458 } 02459 return 0; 02460 }
static int cc_generic_agent_stop_ringing | ( | struct ast_cc_agent * | agent | ) | [static] |
Definition at line 2476 of file ccss.c.
References ast_channel_get_by_name_prefix(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, and ast_cc_agent::device_name.
02477 { 02478 struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name)); 02479 02480 if (!recall_chan) { 02481 return 0; 02482 } 02483 02484 ast_softhangup(recall_chan, AST_SOFTHANGUP_EXPLICIT); 02485 return 0; 02486 }
static int cc_generic_is_device_available | ( | enum ast_device_state | state | ) | [static] |
Definition at line 1020 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().
01021 { 01022 return state == AST_DEVICE_NOT_INUSE || state == AST_DEVICE_UNKNOWN; 01023 }
static int cc_generic_monitor_cancel_available_timer | ( | struct ast_cc_monitor * | monitor, | |
int * | sched_id | |||
) | [static] |
Definition at line 1371 of file ccss.c.
References ast_assert, ast_log_dynamic_level, ast_sched_thread_del, cc_sched_thread, cc_unref(), and monitor.
01372 { 01373 ast_assert(sched_id != NULL); 01374 01375 if (*sched_id == -1) { 01376 return 0; 01377 } 01378 01379 ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n", 01380 monitor->core_id, monitor->interface->device_name); 01381 if (!ast_sched_thread_del(cc_sched_thread, *sched_id)) { 01382 cc_unref(monitor, "Remove scheduler's reference to the monitor"); 01383 } 01384 *sched_id = -1; 01385 return 0; 01386 }
static void cc_generic_monitor_destructor | ( | void * | private_data | ) | [static] |
Definition at line 1388 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, generic_monitor_instance::monitoring, and cc_monitor_backend::next.
01389 { 01390 struct generic_monitor_pvt *gen_mon_pvt = private_data; 01391 struct generic_monitor_instance_list *generic_list; 01392 struct generic_monitor_instance *generic_instance; 01393 01394 if (!private_data) { 01395 /* If the private data is NULL, that means that the monitor hasn't even 01396 * been created yet, but that the destructor was called. While this sort 01397 * of behavior is useful for native monitors, with a generic one, there is 01398 * nothing in particular to do. 01399 */ 01400 return; 01401 } 01402 01403 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n", 01404 gen_mon_pvt->core_id, gen_mon_pvt->device_name); 01405 01406 if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) { 01407 /* If there's no generic list, that means that the monitor is being destroyed 01408 * before we actually got to request CC. Not a biggie. Same in the situation 01409 * below if the list traversal should complete without finding an entry. 01410 */ 01411 ast_free((char *)gen_mon_pvt->device_name); 01412 ast_free(gen_mon_pvt); 01413 return; 01414 } 01415 01416 AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) { 01417 if (generic_instance->core_id == gen_mon_pvt->core_id) { 01418 AST_LIST_REMOVE_CURRENT(next); 01419 ast_free(generic_instance); 01420 break; 01421 } 01422 } 01423 AST_LIST_TRAVERSE_SAFE_END; 01424 01425 if (AST_LIST_EMPTY(&generic_list->list)) { 01426 /* No more monitors with this device name exist. Time to unlink this 01427 * list from the container 01428 */ 01429 ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container"); 01430 } else { 01431 /* There are still instances for this particular device. The situation 01432 * may be that we were attempting a CC recall and a failure occurred, perhaps 01433 * on the agent side. If a failure happens here and the device being monitored 01434 * is available, then we need to signal on the first unsuspended instance that 01435 * the device is available for recall. 01436 */ 01437 01438 /* First things first. We don't even want to consider this action if 01439 * the device in question isn't available right now. 01440 */ 01441 if (generic_list->fit_for_recall 01442 && cc_generic_is_device_available(generic_list->current_state)) { 01443 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01444 if (!generic_instance->is_suspended && generic_instance->monitoring) { 01445 ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor " 01446 "availability due to other instance's failure."); 01447 break; 01448 } 01449 } 01450 } 01451 } 01452 cc_unref(generic_list, "Done with generic list in generic monitor destructor"); 01453 ast_free((char *)gen_mon_pvt->device_name); 01454 ast_free(gen_mon_pvt); 01455 }
static int cc_generic_monitor_request_cc | ( | struct ast_cc_monitor * | monitor, | |
int * | available_timer_id | |||
) | [static] |
Definition at line 1239 of file ccss.c.
References ast_calloc, ast_cc_available_timer_expire(), AST_CC_CCBS, AST_CC_CCNL, AST_CC_CCNR, ast_cc_monitor_request_acked(), ast_free, ast_get_ccbs_available_timer(), ast_get_ccnr_available_timer(), AST_LIST_INSERT_TAIL, ast_sched_thread_add(), ast_strdup, cc_ref(), cc_sched_thread, cc_unref(), create_new_generic_list(), find_generic_monitor_instance_list(), generic_monitor_instance_list::fit_for_recall, generic_monitor_instance_list::list, monitor, cc_monitor_backend::next, and service.
01240 { 01241 struct generic_monitor_instance_list *generic_list; 01242 struct generic_monitor_instance *generic_instance; 01243 struct generic_monitor_pvt *gen_mon_pvt; 01244 enum ast_cc_service_type service = monitor->service_offered; 01245 int when; 01246 01247 /* First things first. Native channel drivers will have their private data allocated 01248 * at the time that they tell the core that they can offer CC. Generic is quite a bit 01249 * different, and we wait until this point to allocate our private data. 01250 */ 01251 if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) { 01252 return -1; 01253 } 01254 01255 if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) { 01256 ast_free(gen_mon_pvt); 01257 return -1; 01258 } 01259 01260 gen_mon_pvt->core_id = monitor->core_id; 01261 01262 monitor->private_data = gen_mon_pvt; 01263 01264 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) { 01265 if (!(generic_list = create_new_generic_list(monitor))) { 01266 return -1; 01267 } 01268 } 01269 01270 if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) { 01271 /* The generic monitor destructor will take care of the appropriate 01272 * deallocations 01273 */ 01274 cc_unref(generic_list, "Generic monitor instance failed to allocate"); 01275 return -1; 01276 } 01277 generic_instance->core_id = monitor->core_id; 01278 generic_instance->monitoring = 1; 01279 AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next); 01280 when = service == AST_CC_CCBS ? ast_get_ccbs_available_timer(monitor->interface->config_params) : 01281 ast_get_ccnr_available_timer(monitor->interface->config_params); 01282 01283 *available_timer_id = ast_sched_thread_add(cc_sched_thread, when * 1000, 01284 ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference")); 01285 if (*available_timer_id == -1) { 01286 cc_unref(monitor, "Failed to schedule available timer. (monitor)"); 01287 cc_unref(generic_list, "Failed to schedule available timer. (generic_list)"); 01288 return -1; 01289 } 01290 /* If the new instance was created as CCNR, then that means this device is not currently 01291 * fit for recall even if it previously was. 01292 */ 01293 if (service == AST_CC_CCNR || service == AST_CC_CCNL) { 01294 generic_list->fit_for_recall = 0; 01295 } 01296 ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.", 01297 monitor->interface->device_name); 01298 cc_unref(generic_list, "Finished with monitor instance reference in request cc callback"); 01299 return 0; 01300 }
static int cc_generic_monitor_suspend | ( | struct ast_cc_monitor * | monitor | ) | [static] |
Definition at line 1302 of file ccss.c.
References ast_cc_monitor_callee_available(), ast_device_state(), AST_LIST_TRAVERSE, cc_generic_is_device_available(), cc_unref(), generic_monitor_instance::core_id, find_generic_monitor_instance_list(), generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, monitor, and cc_monitor_backend::next.
01303 { 01304 struct generic_monitor_instance_list *generic_list; 01305 struct generic_monitor_instance *generic_instance; 01306 enum ast_device_state state = ast_device_state(monitor->interface->device_name); 01307 01308 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) { 01309 return -1; 01310 } 01311 01312 /* First we need to mark this particular monitor as being suspended. */ 01313 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01314 if (generic_instance->core_id == monitor->core_id) { 01315 generic_instance->is_suspended = 1; 01316 break; 01317 } 01318 } 01319 01320 /* If the device being suspended is currently in use, then we don't need to 01321 * take any further actions 01322 */ 01323 if (!cc_generic_is_device_available(state)) { 01324 cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list."); 01325 return 0; 01326 } 01327 01328 /* If the device is not in use, though, then it may be possible to report the 01329 * device's availability using a different monitor which is monitoring the 01330 * same device 01331 */ 01332 01333 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01334 if (!generic_instance->is_suspended) { 01335 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available"); 01336 break; 01337 } 01338 } 01339 cc_unref(generic_list, "Done with generic list in suspend callback"); 01340 return 0; 01341 }
static int cc_generic_monitor_unsuspend | ( | struct ast_cc_monitor * | monitor | ) | [static] |
Definition at line 1343 of file ccss.c.
References ast_cc_monitor_callee_available(), ast_device_state(), AST_LIST_TRAVERSE, cc_generic_is_device_available(), cc_unref(), generic_monitor_instance::core_id, find_generic_monitor_instance_list(), generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, monitor, generic_monitor_instance::monitoring, and cc_monitor_backend::next.
01344 { 01345 struct generic_monitor_instance *generic_instance; 01346 struct generic_monitor_instance_list *generic_list = find_generic_monitor_instance_list(monitor->interface->device_name); 01347 enum ast_device_state state = ast_device_state(monitor->interface->device_name); 01348 01349 if (!generic_list) { 01350 return -1; 01351 } 01352 /* If the device is currently available, we can immediately announce 01353 * its availability 01354 */ 01355 if (cc_generic_is_device_available(state)) { 01356 ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available"); 01357 } 01358 01359 /* In addition, we need to mark this generic_monitor_instance as not being suspended anymore */ 01360 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01361 if (generic_instance->core_id == monitor->core_id) { 01362 generic_instance->is_suspended = 0; 01363 generic_instance->monitoring = 1; 01364 break; 01365 } 01366 } 01367 cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend"); 01368 return 0; 01369 }
static void cc_interface_destroy | ( | void * | data | ) | [static] |
Definition at line 1457 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().
01458 { 01459 struct ast_cc_interface *interface = data; 01460 ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name); 01461 ast_cc_config_params_destroy(interface->config_params); 01462 }
static void cc_interface_tree_destroy | ( | void * | data | ) | [static] |
Definition at line 1578 of file ccss.c.
References AST_LIST_HEAD_DESTROY, AST_LIST_REMOVE_HEAD, cc_unref(), monitor, and cc_monitor_backend::next.
Referenced by cc_interfaces_datastore_init().
01579 { 01580 struct cc_monitor_tree *cc_interface_tree = data; 01581 struct ast_cc_monitor *monitor; 01582 while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) { 01583 if (monitor->callbacks) { 01584 monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id); 01585 } 01586 cc_unref(monitor, "Destroying all monitors"); 01587 } 01588 AST_LIST_HEAD_DESTROY(cc_interface_tree); 01589 }
static int cc_interfaces_datastore_init | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 1858 of file ccss.c.
References ao2_t_alloc, ast_atomic_fetchadd_int(), ast_calloc, ast_cc_request_is_within_limits(), ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_free, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, cc_extension_monitor_init(), cc_interface_tree_destroy(), cc_ref(), cc_unref(), ast_channel::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, dialed_cc_interfaces_info, ast_channel::exten, ast_datastore::inheritance, ast_channel::macrocontext, ast_channel::macroexten, monitor, cc_monitor_backend::next, and S_OR.
Referenced by ast_cc_call_init().
01858 { 01859 struct dialed_cc_interfaces *interfaces; 01860 struct ast_cc_monitor *monitor; 01861 struct ast_datastore *dial_cc_datastore; 01862 01863 /*XXX This may be a bit controversial. In an attempt to not allocate 01864 * extra resources, I make sure that a future request will be within 01865 * limits. The problem here is that it is reasonable to think that 01866 * even if we're not within the limits at this point, we may be by 01867 * the time the requestor will have made his request. This may be 01868 * deleted at some point. 01869 */ 01870 if (!ast_cc_request_is_within_limits()) { 01871 return 0; 01872 } 01873 01874 if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) { 01875 return -1; 01876 } 01877 01878 if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten), S_OR(chan->macrocontext, chan->context), 0))) { 01879 ast_free(interfaces); 01880 return -1; 01881 } 01882 01883 if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) { 01884 cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor"); 01885 ast_free(interfaces); 01886 return -1; 01887 } 01888 01889 if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy, 01890 "Allocate monitor tree"))) { 01891 ast_datastore_free(dial_cc_datastore); 01892 cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor"); 01893 ast_free(interfaces); 01894 return -1; 01895 } 01896 01897 /* Finally, all that allocation is done... */ 01898 AST_LIST_HEAD_INIT(interfaces->interface_tree); 01899 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next); 01900 cc_ref(monitor, "List's reference to extension monitor"); 01901 dial_cc_datastore->data = interfaces; 01902 dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER; 01903 interfaces->dial_parent_id = monitor->id; 01904 interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1); 01905 interfaces->is_original_caller = 1; 01906 ast_channel_lock(chan); 01907 ast_channel_datastore_add(chan, dial_cc_datastore); 01908 ast_channel_unlock(chan); 01909 cc_unref(monitor, "Unreffing allocation's reference"); 01910 return 0; 01911 }
static void cc_monitor_destroy | ( | void * | data | ) | [static] |
Definition at line 1557 of file ccss.c.
References AST_CC_EXTENSION_MONITOR, ast_free, ast_log_dynamic_level, cc_extension_monitor_destructor(), cc_unref(), and monitor.
Referenced by cc_device_monitor_init(), and cc_extension_monitor_init().
01558 { 01559 struct ast_cc_monitor *monitor = data; 01560 /* During the monitor creation process, it is possible for this 01561 * function to be called prior to when callbacks are assigned 01562 * to the monitor. Also, extension monitors do not have callbacks 01563 * assigned to them, so we wouldn't want to segfault when we try 01564 * to destroy one of them. 01565 */ 01566 ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n", 01567 monitor->core_id, monitor->interface->device_name); 01568 if (monitor->interface->monitor_class == AST_CC_EXTENSION_MONITOR) { 01569 cc_extension_monitor_destructor(monitor->private_data); 01570 } 01571 if (monitor->callbacks) { 01572 monitor->callbacks->destructor(monitor->private_data); 01573 } 01574 cc_unref(monitor->interface, "Unreffing tree's reference to interface"); 01575 ast_free(monitor->dialstring); 01576 }
static int cc_monitor_failed | ( | void * | data | ) | [static] |
Definition at line 3615 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cc_failed(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, ast_cc_monitor::core_id, ast_cc_monitor_failure_data::core_id, ast_cc_monitor_failure_data::debug, ast_cc_interface::device_name, ast_cc_monitor_failure_data::device_name, EVENT_FLAG_CC, find_cc_core_instance(), has_device_monitors(), ast_cc_monitor::interface, manager_event, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor::parent_id.
Referenced by ast_cc_monitor_failed().
03616 { 03617 struct ast_cc_monitor_failure_data *failure_data = data; 03618 struct cc_core_instance *core_instance; 03619 struct ast_cc_monitor *monitor_iter; 03620 03621 core_instance = find_cc_core_instance(failure_data->core_id); 03622 if (!core_instance) { 03623 /* Core instance no longer exists or invalid core_id. */ 03624 ast_log_dynamic_level(cc_logger_level, 03625 "Core %d: Could not find core instance for device %s '%s'\n", 03626 failure_data->core_id, failure_data->device_name, failure_data->debug); 03627 ast_free((char *) failure_data->device_name); 03628 ast_free((char *) failure_data->debug); 03629 ast_free(failure_data); 03630 return -1; 03631 } 03632 03633 AST_LIST_LOCK(core_instance->monitors); 03634 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 03635 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 03636 if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) { 03637 AST_LIST_REMOVE_CURRENT(next); 03638 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 03639 monitor_iter->interface->device_name, 1); 03640 monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id); 03641 manager_event(EVENT_FLAG_CC, "CCMonitorFailed", 03642 "CoreID: %d\r\n" 03643 "Callee: %s\r\n", 03644 monitor_iter->core_id, monitor_iter->interface->device_name); 03645 cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference."); 03646 } 03647 } 03648 } 03649 AST_LIST_TRAVERSE_SAFE_END; 03650 03651 if (!has_device_monitors(core_instance)) { 03652 ast_cc_failed(core_instance->core_id, "All monitors have failed\n"); 03653 } 03654 AST_LIST_UNLOCK(core_instance->monitors); 03655 cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n"); 03656 03657 ast_free((char *) failure_data->device_name); 03658 ast_free((char *) failure_data->debug); 03659 ast_free(failure_data); 03660 return 0; 03661 }
static int cc_offer | ( | const int | core_id, | |
const char *const | debug, | |||
... | ||||
) | [static] |
Definition at line 3459 of file ccss.c.
References CC_CALLER_OFFERED, and cc_request_state_change().
Referenced by ast_cc_offer().
03460 { 03461 va_list ap; 03462 int res; 03463 03464 va_start(ap, debug); 03465 res = cc_request_state_change(CC_CALLER_OFFERED, core_id, debug, ap); 03466 va_end(ap); 03467 return res; 03468 }
static int cc_party_b_free | ( | void * | data | ) | [static] |
Definition at line 3761 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().
03762 { 03763 struct cc_core_instance *core_instance = data; 03764 int res = 0; 03765 03766 if (core_instance->agent->callbacks->party_b_free) { 03767 res = core_instance->agent->callbacks->party_b_free(core_instance->agent); 03768 } 03769 cc_unref(core_instance, "Party B free finished. Unref core_instance"); 03770 return res; 03771 }
static void cc_recall_ds_destroy | ( | void * | data | ) | [static] |
Definition at line 3111 of file ccss.c.
References ast_free, cc_unref(), and cc_recall_ds_data::interface_tree.
03112 { 03113 struct cc_recall_ds_data *recall_data = data; 03114 recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree"); 03115 ast_free(recall_data); 03116 }
static void* cc_recall_ds_duplicate | ( | void * | data | ) | [static] |
Definition at line 3097 of file ccss.c.
References ast_calloc, cc_ref(), cc_recall_ds_data::core_id, and cc_recall_ds_data::interface_tree.
03098 { 03099 struct cc_recall_ds_data *old_data = data; 03100 struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data)); 03101 03102 if (!new_data) { 03103 return NULL; 03104 } 03105 new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate"); 03106 new_data->core_id = old_data->core_id; 03107 new_data->nested = 1; 03108 return new_data; 03109 }
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 2962 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.
02963 { 02964 /* Both caller and callee are available, call agent's recall callback 02965 */ 02966 cancel_available_timer(core_instance); 02967 manager_event(EVENT_FLAG_CC, "CCCallerRecalling", 02968 "CoreID: %d\r\n" 02969 "Caller: %s\r\n", 02970 core_instance->core_id, core_instance->agent->device_name); 02971 return 0; 02972 }
static void* cc_ref | ( | void * | obj, | |
const char * | debug | |||
) | [inline, static] |
Definition at line 130 of file ccss.c.
References ao2_t_ref.
Referenced by ast_cc_agent_callback(), ast_cc_call_init(), ast_cc_get_monitor_by_recall_core_id(), ast_handle_cc_control_frame(), ast_setup_cc_recall_datastore(), cc_core_init_instance(), cc_generic_agent_start_offer_timer(), cc_generic_monitor_request_cc(), cc_interfaces_datastore_init(), cc_recall_ds_duplicate(), dialed_cc_interfaces_duplicate(), and generic_agent_devstate_cb().
static int cc_request_state_change | ( | enum cc_state | state, | |
const int | core_id, | |||
const char * | debug, | |||
va_list | ap | |||
) | [static] |
Definition at line 3047 of file ccss.c.
References args, ast_calloc, ast_free, ast_log_dynamic_level, ast_taskprocessor_push(), cc_core_taskprocessor, cc_do_state_change(), cc_unref(), cc_core_instance::core_id, cc_state_change_args::core_instance, dummy(), and find_cc_core_instance().
Referenced by ast_cc_agent_accept_request(), ast_cc_agent_caller_available(), ast_cc_agent_caller_busy(), ast_cc_agent_recalling(), ast_cc_completed(), ast_cc_failed(), ast_cc_monitor_callee_available(), ast_cc_monitor_request_acked(), and cc_offer().
03048 { 03049 int res; 03050 int debuglen; 03051 char dummy[1]; 03052 va_list aq; 03053 struct cc_core_instance *core_instance; 03054 struct cc_state_change_args *args; 03055 /* This initial call to vsnprintf is simply to find what the 03056 * size of the string needs to be 03057 */ 03058 va_copy(aq, ap); 03059 /* We add 1 to the result since vsnprintf's return does not 03060 * include the terminating null byte 03061 */ 03062 debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1; 03063 va_end(aq); 03064 03065 if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) { 03066 return -1; 03067 } 03068 03069 core_instance = find_cc_core_instance(core_id); 03070 if (!core_instance) { 03071 ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n", 03072 core_id); 03073 ast_free(args); 03074 return -1; 03075 } 03076 03077 args->core_instance = core_instance; 03078 args->state = state; 03079 args->core_id = core_id; 03080 vsnprintf(args->debug, debuglen, debug, ap); 03081 03082 res = ast_taskprocessor_push(cc_core_taskprocessor, cc_do_state_change, args); 03083 if (res) { 03084 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed"); 03085 ast_free(args); 03086 } 03087 return res; 03088 }
static const char* cc_service_to_string | ( | enum ast_cc_service_type | service | ) | [static] |
Definition at line 398 of file ccss.c.
References cc_service_to_string_map.
Referenced by ast_handle_cc_control_frame(), and cc_cli_print_monitor_stats().
00399 { 00400 return cc_service_to_string_map[service].service_string; 00401 }
static const char* cc_state_to_string | ( | enum cc_state | state | ) | [static] |
Definition at line 393 of file ccss.c.
References cc_state_to_string_map.
Referenced by cc_do_state_change(), and print_stats_cb().
00394 { 00395 return cc_state_to_string_map[state].state_string; 00396 }
static int cc_status_request | ( | void * | data | ) | [static] |
Definition at line 3698 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().
03699 { 03700 struct cc_core_instance *core_instance= data; 03701 int res; 03702 03703 res = core_instance->agent->callbacks->status_request(core_instance->agent); 03704 cc_unref(core_instance, "Status request finished. Unref core instance"); 03705 return res; 03706 }
static int cc_status_response | ( | void * | data | ) | [static] |
Definition at line 3794 of file ccss.c.
References args, AST_CC_DEVICE_MONITOR, ast_device_state(), ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_unref(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor_callbacks::status_response.
Referenced by ast_cc_agent_status_response().
03795 { 03796 struct cc_status_response_args *args = data; 03797 struct cc_core_instance *core_instance = args->core_instance; 03798 struct ast_cc_monitor *monitor_iter; 03799 enum ast_device_state devstate = args->devstate; 03800 03801 ast_free(args); 03802 03803 AST_LIST_LOCK(core_instance->monitors); 03804 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 03805 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR && 03806 monitor_iter->callbacks->status_response) { 03807 monitor_iter->callbacks->status_response(monitor_iter, devstate); 03808 } 03809 } 03810 AST_LIST_UNLOCK(core_instance->monitors); 03811 cc_unref(core_instance, "Status response finished. Unref core instance"); 03812 return 0; 03813 }
static int cc_stop_ringing | ( | void * | data | ) | [static] |
Definition at line 3724 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().
03725 { 03726 struct cc_core_instance *core_instance = data; 03727 int res = 0; 03728 03729 if (core_instance->agent->callbacks->stop_ringing) { 03730 res = core_instance->agent->callbacks->stop_ringing(core_instance->agent); 03731 } 03732 /* If an agent is being asked to stop ringing, then he needs to be prepared if for 03733 * whatever reason he needs to be called back again. The proper state to be in to 03734 * detect such a circumstance is the CC_ACTIVE state. 03735 * 03736 * We get to this state using the slightly unintuitive method of calling 03737 * ast_cc_monitor_request_acked because it gets us to the proper state. 03738 */ 03739 ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.", 03740 core_instance->agent->device_name); 03741 cc_unref(core_instance, "Stop ringing finished. Unref core_instance"); 03742 return res; 03743 }
static void cc_unique_append | ( | struct ast_str * | str, | |
const char * | dialstring | |||
) | [static] |
Definition at line 3277 of file ccss.c.
References AST_CHANNEL_NAME, ast_str_append(), ast_str_buffer(), ast_strlen_zero(), and str.
Referenced by build_cc_interfaces_chanvar().
03278 { 03279 char dialstring_search[AST_CHANNEL_NAME]; 03280 03281 if (ast_strlen_zero(dialstring)) { 03282 /* No dialstring to append. */ 03283 return; 03284 } 03285 snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&'); 03286 if (strstr(ast_str_buffer(str), dialstring_search)) { 03287 return; 03288 } 03289 ast_str_append(&str, 0, "%s", dialstring_search); 03290 }
static void* cc_unref | ( | void * | obj, | |
const char * | debug | |||
) | [inline, static] |
Definition at line 136 of file ccss.c.
References ao2_t_ref.
Referenced by ast_cc_agent_callback(), ast_cc_agent_status_response(), ast_cc_available_timer_expire(), ast_cc_call_init(), ast_cc_get_monitor_by_recall_core_id(), ast_cc_monitor_party_b_free(), ast_cc_monitor_status_request(), ast_cc_monitor_stop_ringing(), ast_handle_cc_control_frame(), ast_setup_cc_recall_datastore(), cancel_available_timer(), cc_agent_init(), cc_core_init_instance(), cc_core_instance_destructor(), cc_device_monitor_init(), cc_do_state_change(), cc_extension_monitor_init(), cc_generic_agent_stop_offer_timer(), cc_generic_monitor_cancel_available_timer(), cc_generic_monitor_destructor(), cc_generic_monitor_request_cc(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), cc_interface_tree_destroy(), cc_interfaces_datastore_init(), cc_monitor_destroy(), cc_monitor_failed(), cc_party_b_free(), cc_recall_ds_destroy(), cc_request_state_change(), cc_status_request(), cc_status_response(), cc_stop_ringing(), cccancel_exec(), ccreq_exec(), complete_core_id(), create_new_generic_list(), dialed_cc_interfaces_destroy(), generic_agent_devstate_cb(), generic_agent_devstate_unsubscribe(), generic_monitor_devstate_tp_cb(), offer_timer_expire(), request_cc(), suspend(), and unsuspend().
static int cccancel_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 4030 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_core_instances, 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().
04031 { 04032 struct cc_core_instance *core_instance; 04033 char device_name[AST_CHANNEL_NAME]; 04034 unsigned long match_flags; 04035 int res; 04036 04037 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 04038 04039 match_flags = MATCH_REQUEST; 04040 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) { 04041 ast_log_dynamic_level(cc_logger_level, "Cannot find CC transaction to cancel for caller %s\n", device_name); 04042 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL"); 04043 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NO_CORE_INSTANCE"); 04044 return 0; 04045 } 04046 04047 if (strcmp(core_instance->agent->callbacks->type, "generic")) { 04048 ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calles with a generic agent\n"); 04049 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel"); 04050 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL"); 04051 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NOT_GENERIC"); 04052 return 0; 04053 } 04054 res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s", 04055 core_instance->core_id, device_name); 04056 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel"); 04057 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", res ? "FAIL" : "SUCCESS"); 04058 if (res) { 04059 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "UNSPECIFIED"); 04060 } 04061 return 0; 04062 }
static int ccreq_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 3979 of file ccss.c.
References cc_core_instance::agent, ao2_t_callback_data, ast_cc_agent_accept_request(), ast_cc_failed(), ast_cc_request_is_within_limits(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_log_dynamic_level, ast_cc_agent::callbacks, cc_core_instances, cc_unref(), cc_core_instance::core_id, match_agent(), MATCH_NO_REQUEST, pbx_builtin_setvar_helper(), and ast_cc_agent_callbacks::type.
Referenced by ast_cc_init().
03980 { 03981 struct cc_core_instance *core_instance; 03982 char device_name[AST_CHANNEL_NAME]; 03983 unsigned long match_flags; 03984 int res; 03985 03986 ast_channel_get_device_name(chan, device_name, sizeof(device_name)); 03987 03988 match_flags = MATCH_NO_REQUEST; 03989 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) { 03990 ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name); 03991 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL"); 03992 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NO_CORE_INSTANCE"); 03993 return 0; 03994 } 03995 03996 ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n", 03997 core_instance->core_id, device_name); 03998 03999 if (strcmp(core_instance->agent->callbacks->type, "generic")) { 04000 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n", 04001 core_instance->core_id); 04002 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL"); 04003 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NOT_GENERIC"); 04004 cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent"); 04005 return 0; 04006 } 04007 04008 if (!ast_cc_request_is_within_limits()) { 04009 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n", 04010 core_instance->core_id); 04011 ast_cc_failed(core_instance->core_id, "Too many CC requests\n"); 04012 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL"); 04013 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "TOO_MANY_REQUESTS"); 04014 cc_unref(core_instance, "Unref core_instance since too many CC requests"); 04015 return 0; 04016 } 04017 04018 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); 04019 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS"); 04020 if (res) { 04021 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "UNSPECIFIED"); 04022 } 04023 04024 cc_unref(core_instance, "Done with CallCompletionRequest"); 04025 return 0; 04026 }
static void check_callback_sanity | ( | const struct ast_cc_agent_callbacks * | callbacks | ) | [static] |
Definition at line 2259 of file ccss.c.
References ast_assert, cc_monitor_backend::callbacks, and ast_cc_monitor_callbacks::destructor.
Referenced by cc_agent_init().
02260 { 02261 ast_assert(callbacks->init != NULL); 02262 ast_assert(callbacks->start_offer_timer != NULL); 02263 ast_assert(callbacks->stop_offer_timer != NULL); 02264 ast_assert(callbacks->respond != NULL); 02265 ast_assert(callbacks->status_request != NULL); 02266 ast_assert(callbacks->start_monitoring != NULL); 02267 ast_assert(callbacks->callee_available != NULL); 02268 ast_assert(callbacks->destructor != NULL); 02269 }
static char* complete_core_id | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 4224 of file ccss.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, cc_core_instances, cc_unref(), and cc_core_instance::core_id.
Referenced by handle_cc_kill().
04225 { 04226 int which = 0; 04227 int wordlen = strlen(word); 04228 char *ret = NULL; 04229 struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0); 04230 struct cc_core_instance *core_instance; 04231 04232 for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance")); 04233 cc_unref(core_instance, "CLI tab completion iteration")) { 04234 char core_id_str[20]; 04235 snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id); 04236 if (!strncmp(word, core_id_str, wordlen) && ++which > state) { 04237 ret = ast_strdup(core_id_str); 04238 cc_unref(core_instance, "Found a matching core ID for CLI tab-completion"); 04239 break; 04240 } 04241 } 04242 ao2_iterator_destroy(&core_iter); 04243 04244 return ret; 04245 }
static long count_agents | ( | const char *const | caller, | |
const int | core_id_exception | |||
) | [static] |
Definition at line 2233 of file ccss.c.
References ao2_t_callback_data, ast_log_dynamic_level, cc_core_instances, count_agents_cb_data::core_id_exception, count_agents_cb_data::count, count_agents_cb(), and OBJ_NODATA.
Referenced by agents_show(), agents_show_online(), and cc_core_init_instance().
02234 { 02235 struct count_agents_cb_data data = {.core_id_exception = core_id_exception,}; 02236 02237 ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents"); 02238 ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count); 02239 return data.count; 02240 }
static int count_agents_cb | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 516 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().
00517 { 00518 struct cc_core_instance *core_instance = obj; 00519 const char *name = arg; 00520 struct count_agents_cb_data *cb_data = data; 00521 00522 if (cb_data->core_id_exception == core_instance->core_id) { 00523 ast_log_dynamic_level(cc_logger_level, "Found agent with core_id %d but not counting it toward total\n", core_instance->core_id); 00524 return 0; 00525 } 00526 00527 if (core_instance->current_state >= CC_CALLER_REQUESTED && !strcmp(core_instance->agent->device_name, name)) { 00528 cb_data->count++; 00529 } 00530 return 0; 00531 }
static int count_monitors_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4070 of file ccss.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, count_monitors_cb_data::count, ast_cc_interface::device_name, count_monitors_cb_data::device_name, ast_cc_monitor::interface, ast_cc_interface::monitor_type, count_monitors_cb_data::monitor_type, cc_core_instance::monitors, and cc_monitor_backend::next.
Referenced by ast_cc_monitor_count().
04071 { 04072 struct cc_core_instance *core_instance = obj; 04073 struct count_monitors_cb_data *cb_data = arg; 04074 const char *device_name = cb_data->device_name; 04075 const char *monitor_type = cb_data->monitor_type; 04076 struct ast_cc_monitor *monitor_iter; 04077 04078 AST_LIST_LOCK(core_instance->monitors); 04079 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) { 04080 if (!strcmp(monitor_iter->interface->device_name, device_name) && 04081 !strcmp(monitor_iter->interface->monitor_type, monitor_type)) { 04082 cb_data->count++; 04083 break; 04084 } 04085 } 04086 AST_LIST_UNLOCK(core_instance->monitors); 04087 return 0; 04088 }
static struct generic_monitor_instance_list* create_new_generic_list | ( | struct ast_cc_monitor * | monitor | ) | [static] |
Definition at line 1124 of file ccss.c.
References ao2_t_alloc, ao2_t_link, ast_device_state(), AST_EVENT_DEVICE_STATE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_STATE, ast_event_subscribe(), ast_strdup, cc_unref(), generic_monitor_devstate_cb(), generic_monitor_instance_list_destructor(), generic_monitors, and monitor.
Referenced by cc_generic_monitor_request_cc().
01125 { 01126 struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list), 01127 generic_monitor_instance_list_destructor, "allocate generic monitor instance list"); 01128 01129 if (!generic_list) { 01130 return NULL; 01131 } 01132 01133 if (!(generic_list->device_name = ast_strdup(monitor->interface->device_name))) { 01134 cc_unref(generic_list, "Failed to strdup the monitor's device name"); 01135 return NULL; 01136 } 01137 01138 if (!(generic_list->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, 01139 generic_monitor_devstate_cb, "Requesting CC", NULL, 01140 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, monitor->interface->device_name, 01141 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_EXISTS, 01142 AST_EVENT_IE_END))) { 01143 cc_unref(generic_list, "Failed to subscribe to device state"); 01144 return NULL; 01145 } 01146 generic_list->current_state = ast_device_state(monitor->interface->device_name); 01147 ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list"); 01148 return generic_list; 01149 }
static void dialed_cc_interfaces_destroy | ( | void * | data | ) | [static] |
Definition at line 1664 of file ccss.c.
References ast_free, cc_unref(), and dialed_cc_interfaces::interface_tree.
01665 { 01666 struct dialed_cc_interfaces *cc_interfaces = data; 01667 cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree"); 01668 ast_free(cc_interfaces); 01669 }
static void* dialed_cc_interfaces_duplicate | ( | void * | data | ) | [static] |
Definition at line 1684 of file ccss.c.
References ast_calloc, cc_ref(), dialed_cc_interfaces::core_id, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces::ignore, and dialed_cc_interfaces::interface_tree.
01685 { 01686 struct dialed_cc_interfaces *old_cc_interfaces = data; 01687 struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces)); 01688 if (!new_cc_interfaces) { 01689 return NULL; 01690 } 01691 new_cc_interfaces->ignore = old_cc_interfaces->ignore; 01692 new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id; 01693 new_cc_interfaces->is_original_caller = 0; 01694 cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree"); 01695 new_cc_interfaces->core_id = old_cc_interfaces->core_id; 01696 new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree; 01697 return new_cc_interfaces; 01698 }
static struct extension_monitor_pvt* extension_monitor_pvt_init | ( | void | ) | [static] |
Definition at line 1715 of file ccss.c.
References ast_calloc, and AST_LIST_HEAD_INIT_NOLOCK.
Referenced by cc_extension_monitor_init().
01716 { 01717 struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt)); 01718 if (!ext_pvt) { 01719 return NULL; 01720 } 01721 AST_LIST_HEAD_INIT_NOLOCK(&ext_pvt->child_dialstrings); 01722 return ext_pvt; 01723 }
static struct ast_cc_agent_callbacks* find_agent_callbacks | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 976 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().
00977 { 00978 struct cc_agent_backend *backend; 00979 const struct ast_cc_agent_callbacks *callbacks = NULL; 00980 struct ast_cc_config_params *cc_params; 00981 char type[32]; 00982 00983 cc_params = ast_channel_get_cc_config_params(chan); 00984 if (!cc_params) { 00985 return NULL; 00986 } 00987 switch (ast_get_cc_agent_policy(cc_params)) { 00988 case AST_CC_AGENT_GENERIC: 00989 ast_copy_string(type, "generic", sizeof(type)); 00990 break; 00991 case AST_CC_AGENT_NATIVE: 00992 ast_channel_get_cc_agent_type(chan, type, sizeof(type)); 00993 break; 00994 default: 00995 ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n"); 00996 return NULL; 00997 } 00998 00999 AST_RWLIST_RDLOCK(&cc_agent_backends); 01000 AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) { 01001 if (!strcmp(backend->callbacks->type, type)) { 01002 ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type); 01003 callbacks = backend->callbacks; 01004 break; 01005 } 01006 } 01007 AST_RWLIST_UNLOCK(&cc_agent_backends); 01008 return callbacks; 01009 }
static struct cc_core_instance* find_cc_core_instance | ( | const int | core_id | ) | [static] |
Definition at line 417 of file ccss.c.
References ao2_t_find, cc_core_instances, cc_core_instance::core_id, and OBJ_POINTER.
Referenced by ast_cc_agent_status_response(), ast_cc_get_monitor_by_recall_core_id(), ast_cc_monitor_party_b_free(), ast_cc_monitor_status_request(), ast_cc_monitor_stop_ringing(), ast_handle_cc_control_frame(), ast_setup_cc_recall_datastore(), cc_monitor_failed(), and cc_request_state_change().
00418 { 00419 struct cc_core_instance finder = {.core_id = core_id,}; 00420 00421 return ao2_t_find(cc_core_instances, &finder, OBJ_POINTER, "Finding a core_instance"); 00422 }
static struct generic_monitor_instance_list* find_generic_monitor_instance_list | ( | const char *const | device_name | ) | [static] |
Definition at line 1104 of file ccss.c.
References ao2_t_find, generic_monitor_instance_list::device_name, generic_monitors, and OBJ_POINTER.
Referenced by cc_generic_monitor_destructor(), cc_generic_monitor_request_cc(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), and generic_monitor_devstate_tp_cb().
01105 { 01106 struct generic_monitor_instance_list finder = {.device_name = device_name}; 01107 01108 return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list"); 01109 }
static struct ast_cc_monitor_callbacks* find_monitor_callbacks | ( | const char *const | type | ) | [static] |
Definition at line 907 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().
00908 { 00909 struct cc_monitor_backend *backend; 00910 const struct ast_cc_monitor_callbacks *callbacks = NULL; 00911 00912 AST_RWLIST_RDLOCK(&cc_monitor_backends); 00913 AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) { 00914 if (!strcmp(backend->callbacks->type, type)) { 00915 ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type); 00916 callbacks = backend->callbacks; 00917 break; 00918 } 00919 } 00920 AST_RWLIST_UNLOCK(&cc_monitor_backends); 00921 return callbacks; 00922 }
static void generic_agent_devstate_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 2500 of file ccss.c.
References ast_cc_agent_caller_available(), ast_device_state(), ast_event_get_ie_uint(), AST_EVENT_IE_STATE, ast_taskprocessor_push(), cc_core_taskprocessor, 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().
02501 { 02502 struct ast_cc_agent *agent = userdata; 02503 enum ast_device_state new_state; 02504 02505 new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 02506 if (!cc_generic_is_device_available(new_state)) { 02507 /* Not interested in this new state of the device. It is still busy. */ 02508 return; 02509 } 02510 02511 /* We can't unsubscribe from device state events here because it causes a deadlock */ 02512 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_agent_devstate_unsubscribe, 02513 cc_ref(agent, "ref agent for device state unsubscription"))) { 02514 cc_unref(agent, "Unref agent unsubscribing from devstate failed"); 02515 } 02516 ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name); 02517 }
static int generic_agent_devstate_unsubscribe | ( | void * | data | ) | [static] |
Definition at line 2488 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().
02489 { 02490 struct ast_cc_agent *agent = data; 02491 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02492 02493 if (generic_pvt->sub != NULL) { 02494 generic_pvt->sub = ast_event_unsubscribe(generic_pvt->sub); 02495 } 02496 cc_unref(agent, "Done unsubscribing from devstate"); 02497 return 0; 02498 }
static int generic_monitor_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1096 of file ccss.c.
References CMP_MATCH, CMP_STOP, and generic_monitor_instance_list::device_name.
Referenced by ast_cc_init().
01097 { 01098 const struct generic_monitor_instance_list *generic_list1 = obj; 01099 const struct generic_monitor_instance_list *generic_list2 = arg; 01100 01101 return !strcmp(generic_list1->device_name, generic_list2->device_name) ? CMP_MATCH | CMP_STOP : 0; 01102 }
static void generic_monitor_devstate_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 1204 of file ccss.c.
References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_STATE, ast_free, ast_strdup, ast_taskprocessor_push(), cc_core_taskprocessor, and generic_monitor_devstate_tp_cb().
Referenced by create_new_generic_list().
01205 { 01206 /* Wow, it's cool that we've picked up on a state change, but we really want 01207 * the actual work to be done in the core's taskprocessor execution thread 01208 * so that all monitor operations can be serialized. Locks?! We don't need 01209 * no steenkin' locks! 01210 */ 01211 struct generic_tp_cb_data *gtcd = ast_calloc(1, sizeof(*gtcd)); 01212 01213 if (!gtcd) { 01214 return; 01215 } 01216 01217 if (!(gtcd->device_name = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE)))) { 01218 ast_free(gtcd); 01219 return; 01220 } 01221 gtcd->new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 01222 01223 if (ast_taskprocessor_push(cc_core_taskprocessor, generic_monitor_devstate_tp_cb, gtcd)) { 01224 ast_free((char *)gtcd->device_name); 01225 ast_free(gtcd); 01226 } 01227 }
static int generic_monitor_devstate_tp_cb | ( | void * | data | ) | [static] |
Definition at line 1156 of file ccss.c.
References ast_cc_monitor_callee_available(), AST_DEVICE_BUSY, AST_DEVICE_INUSE, ast_device_state(), 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, generic_tp_cb_data::new_state, and cc_monitor_backend::next.
Referenced by generic_monitor_devstate_cb().
01157 { 01158 struct generic_tp_cb_data *gtcd = data; 01159 enum ast_device_state new_state = gtcd->new_state; 01160 enum ast_device_state previous_state = gtcd->new_state; 01161 const char *monitor_name = gtcd->device_name; 01162 struct generic_monitor_instance_list *generic_list; 01163 struct generic_monitor_instance *generic_instance; 01164 01165 if (!(generic_list = find_generic_monitor_instance_list(monitor_name))) { 01166 /* The most likely cause for this is that we destroyed the monitor in the 01167 * time between subscribing to its device state and the time this executes. 01168 * Not really a big deal. 01169 */ 01170 ast_free((char *) gtcd->device_name); 01171 ast_free(gtcd); 01172 return 0; 01173 } 01174 01175 if (generic_list->current_state == new_state) { 01176 /* The device state hasn't actually changed, so we don't really care */ 01177 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback"); 01178 ast_free((char *) gtcd->device_name); 01179 ast_free(gtcd); 01180 return 0; 01181 } 01182 01183 previous_state = generic_list->current_state; 01184 generic_list->current_state = new_state; 01185 01186 if (cc_generic_is_device_available(new_state) && 01187 (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE || 01188 previous_state == AST_DEVICE_BUSY)) { 01189 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) { 01190 if (!generic_instance->is_suspended && generic_instance->monitoring) { 01191 generic_instance->monitoring = 0; 01192 generic_list->fit_for_recall = 1; 01193 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available"); 01194 break; 01195 } 01196 } 01197 } 01198 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback"); 01199 ast_free((char *) gtcd->device_name); 01200 ast_free(gtcd); 01201 return 0; 01202 }
static int generic_monitor_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1090 of file ccss.c.
References ast_str_hash(), and generic_monitor_instance_list::device_name.
Referenced by ast_cc_init().
01091 { 01092 const struct generic_monitor_instance_list *generic_list = obj; 01093 return ast_str_hash(generic_list->device_name); 01094 }
static void generic_monitor_instance_list_destructor | ( | void * | obj | ) | [static] |
Definition at line 1111 of file ccss.c.
References ast_event_unsubscribe(), ast_free, AST_LIST_REMOVE_HEAD, generic_monitor_instance_list::device_name, generic_monitor_instance_list::list, cc_monitor_backend::next, and generic_monitor_instance_list::sub.
Referenced by create_new_generic_list().
01112 { 01113 struct generic_monitor_instance_list *generic_list = obj; 01114 struct generic_monitor_instance *generic_instance; 01115 01116 generic_list->sub = ast_event_unsubscribe(generic_list->sub); 01117 while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) { 01118 ast_free(generic_instance); 01119 } 01120 ast_free((char *)generic_list->device_name); 01121 }
static void* generic_recall | ( | void * | data | ) | [static] |
Definition at line 2538 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().
02539 { 02540 struct ast_cc_agent *agent = data; 02541 struct cc_generic_agent_pvt *generic_pvt = agent->private_data; 02542 const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name)); 02543 const char *tech; 02544 char *target; 02545 int reason; 02546 struct ast_channel *chan; 02547 const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params); 02548 unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000; 02549 02550 tech = interface; 02551 if ((target = strchr(interface, '/'))) { 02552 *target++ = '\0'; 02553 } 02554 if (!(chan = ast_request_and_dial(tech, AST_FORMAT_SLINEAR, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) { 02555 /* Hmm, no channel. Sucks for you, bud. 02556 */ 02557 ast_log_dynamic_level(cc_logger_level, "Core %d: Failed to call back %s for reason %d\n", 02558 agent->core_id, agent->device_name, reason); 02559 ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target); 02560 return NULL; 02561 } 02562 02563 /* We have a channel. It's time now to set up the datastore of recalled CC interfaces. 02564 * This will be a common task for all recall functions. If it were possible, I'd have 02565 * the core do it automatically, but alas I cannot. Instead, I will provide a public 02566 * function to do so. 02567 */ 02568 ast_setup_cc_recall_datastore(chan, agent->core_id); 02569 ast_cc_agent_set_interfaces_chanvar(chan); 02570 02571 ast_copy_string(chan->exten, generic_pvt->exten, sizeof(chan->exten)); 02572 ast_copy_string(chan->context, generic_pvt->context, sizeof(chan->context)); 02573 chan->priority = 1; 02574 02575 pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten); 02576 pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context); 02577 02578 if (!ast_strlen_zero(callback_macro)) { 02579 ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback macro configured for agent %s\n", 02580 agent->core_id, agent->device_name); 02581 if (ast_app_run_macro(NULL, chan, callback_macro, NULL)) { 02582 ast_cc_failed(agent->core_id, "Callback macro to %s failed. Maybe a hangup?", agent->device_name); 02583 ast_hangup(chan); 02584 return NULL; 02585 } 02586 } 02587 ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling", agent->device_name); 02588 ast_pbx_start(chan); 02589 return NULL; 02590 }
static char* handle_cc_kill | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4247 of file ccss.c.
References ao2_t_callback, ast_cli_args::argc, ast_cli_args::argv, ast_cli_complete(), cc_core_instances, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_id(), cc_core_instance::core_id, errno, kill_cores(), ast_cli_args::line, ast_cli_args::n, OBJ_NODATA, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
04248 { 04249 static const char * const option[] = { "core", "all", NULL }; 04250 04251 switch (cmd) { 04252 case CLI_INIT: 04253 e->command = "cc cancel"; 04254 e->usage = 04255 "Usage: cc cancel can be used in two ways.\n" 04256 " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n" 04257 " core ID equal to the specified core ID.\n" 04258 " 2. 'cc cancel all' will cancel all active CC transactions.\n"; 04259 return NULL; 04260 case CLI_GENERATE: 04261 if (a->pos == 2) { 04262 return ast_cli_complete(a->word, option, a->n); 04263 } 04264 if (a->pos == 3) { 04265 return complete_core_id(a->line, a->word, a->pos, a->n); 04266 } 04267 return NULL; 04268 } 04269 04270 if (a->argc == 4) { 04271 int core_id; 04272 char *endptr; 04273 if (strcasecmp(a->argv[2], "core")) { 04274 return CLI_SHOWUSAGE; 04275 } 04276 core_id = strtol(a->argv[3], &endptr, 10); 04277 if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) { 04278 return CLI_SHOWUSAGE; 04279 } 04280 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id"); 04281 } else if (a->argc == 3) { 04282 if (strcasecmp(a->argv[2], "all")) { 04283 return CLI_SHOWUSAGE; 04284 } 04285 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores"); 04286 } else { 04287 return CLI_SHOWUSAGE; 04288 } 04289 04290 return CLI_SUCCESS; 04291 }
static char* handle_cc_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4180 of file ccss.c.
References ast_cli_args::argc, ast_free, ast_malloc, ast_taskprocessor_push(), cc_cli_output_status(), cc_core_taskprocessor, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
04181 { 04182 int *cli_fd; 04183 04184 switch (cmd) { 04185 case CLI_INIT: 04186 e->command = "cc report status"; 04187 e->usage = 04188 "Usage: cc report status\n" 04189 " Report the current status of any ongoing CC transactions\n"; 04190 return NULL; 04191 case CLI_GENERATE: 04192 return NULL; 04193 } 04194 04195 if (a->argc != 3) { 04196 return CLI_SHOWUSAGE; 04197 } 04198 04199 cli_fd = ast_malloc(sizeof(*cli_fd)); 04200 if (!cli_fd) { 04201 return CLI_FAILURE; 04202 } 04203 04204 *cli_fd = a->fd; 04205 04206 if (ast_taskprocessor_push(cc_core_taskprocessor, cc_cli_output_status, cli_fd)) { 04207 ast_free(cli_fd); 04208 return CLI_FAILURE; 04209 } 04210 return CLI_SUCCESS; 04211 }
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 2794 of file ccss.c.
References AST_CC_DEVICE_MONITOR, AST_LIST_TRAVERSE, ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, and cc_monitor_backend::next.
Referenced by cancel_available_timer(), cc_monitor_failed(), request_cc(), suspend(), and unsuspend().
02795 { 02796 struct ast_cc_monitor *iter; 02797 int res = 0; 02798 02799 AST_LIST_TRAVERSE(core_instance->monitors, iter, next) { 02800 if (iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02801 res = 1; 02802 break; 02803 } 02804 } 02805 02806 return res; 02807 }
static void initialize_cc_max_requests | ( | void | ) | [static] |
Definition at line 4099 of file ccss.c.
References ast_config_destroy(), ast_config_load2(), ast_log(), ast_strlen_zero(), ast_variable_retrieve(), config_flags, CONFIG_STATUS_FILEINVALID, GLOBAL_CC_MAX_REQUESTS_DEFAULT, and LOG_WARNING.
Referenced by ast_cc_init().
04100 { 04101 struct ast_config *cc_config; 04102 const char *cc_max_requests_str; 04103 struct ast_flags config_flags = {0,}; 04104 char *endptr; 04105 04106 cc_config = ast_config_load2("ccss.conf", "ccss", config_flags); 04107 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) { 04108 ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests default\n"); 04109 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT; 04110 return; 04111 } 04112 04113 if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) { 04114 ast_config_destroy(cc_config); 04115 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT; 04116 return; 04117 } 04118 04119 global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10); 04120 04121 if (!ast_strlen_zero(endptr)) { 04122 ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n"); 04123 global_cc_max_requests = GLOBAL_CC_MAX_REQUESTS_DEFAULT; 04124 } 04125 04126 ast_config_destroy(cc_config); 04127 return; 04128 }
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 2698 of file ccss.c.
References cc_core_instance::agent, AST_CC_AGENT_SKIP_OFFER, ast_log_dynamic_level, ast_test_flag, CC_ACTIVE, CC_AVAILABLE, CC_CALLEE_READY, CC_CALLER_BUSY, CC_CALLER_OFFERED, CC_CALLER_REQUESTED, CC_COMPLETE, CC_FAILED, CC_RECALLING, and ast_cc_agent::core_id.
Referenced by cc_do_state_change().
02699 { 02700 int is_valid = 0; 02701 switch (new_state) { 02702 case CC_AVAILABLE: 02703 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to state %d? That should never happen.\n", 02704 agent->core_id, new_state); 02705 break; 02706 case CC_CALLER_OFFERED: 02707 if (current_state == CC_AVAILABLE) { 02708 is_valid = 1; 02709 } 02710 break; 02711 case CC_CALLER_REQUESTED: 02712 if (current_state == CC_CALLER_OFFERED || 02713 (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) { 02714 is_valid = 1; 02715 } 02716 break; 02717 case CC_ACTIVE: 02718 if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) { 02719 is_valid = 1; 02720 } 02721 break; 02722 case CC_CALLEE_READY: 02723 if (current_state == CC_ACTIVE) { 02724 is_valid = 1; 02725 } 02726 break; 02727 case CC_CALLER_BUSY: 02728 if (current_state == CC_CALLEE_READY) { 02729 is_valid = 1; 02730 } 02731 break; 02732 case CC_RECALLING: 02733 if (current_state == CC_CALLEE_READY) { 02734 is_valid = 1; 02735 } 02736 break; 02737 case CC_COMPLETE: 02738 if (current_state == CC_RECALLING) { 02739 is_valid = 1; 02740 } 02741 break; 02742 case CC_FAILED: 02743 is_valid = 1; 02744 break; 02745 default: 02746 ast_log_dynamic_level(cc_logger_level, "Core %d: Asked to change to unknown state %d\n", 02747 agent->core_id, new_state); 02748 break; 02749 } 02750 02751 return is_valid; 02752 }
static int kill_cores | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4213 of file ccss.c.
References ast_cc_failed(), and cc_core_instance::core_id.
Referenced by handle_cc_kill().
04214 { 04215 int *core_id = arg; 04216 struct cc_core_instance *core_instance = obj; 04217 04218 if (!core_id || (core_instance->core_id == *core_id)) { 04219 ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n"); 04220 } 04221 return 0; 04222 }
static void kill_duplicate_offers | ( | char * | caller | ) | [static] |
Definition at line 2242 of file ccss.c.
References ao2_iterator_destroy(), ao2_t_callback_data, cc_core_instances, match_agent(), MATCH_NO_REQUEST, OBJ_MULTIPLE, and OBJ_UNLINK.
Referenced by cc_core_init_instance().
02243 { 02244 unsigned long match_flags = MATCH_NO_REQUEST; 02245 struct ao2_iterator *dups_iter; 02246 02247 /* 02248 * Must remove the ref that was in cc_core_instances outside of 02249 * the container lock to prevent deadlock. 02250 */ 02251 dups_iter = ao2_t_callback_data(cc_core_instances, OBJ_MULTIPLE | OBJ_UNLINK, 02252 match_agent, caller, &match_flags, "Killing duplicate offers"); 02253 if (dups_iter) { 02254 /* Now actually unref any duplicate offers by simply destroying the iterator. */ 02255 ao2_iterator_destroy(dups_iter); 02256 } 02257 }
static int match_agent | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 478 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().
00479 { 00480 struct cc_core_instance *core_instance = obj; 00481 const char *name = arg; 00482 unsigned long match_flags = *(unsigned long *)data; 00483 int possible_match = 0; 00484 00485 if ((match_flags & MATCH_NO_REQUEST) && core_instance->current_state < CC_CALLER_REQUESTED) { 00486 possible_match = 1; 00487 } 00488 00489 if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) { 00490 possible_match = 1; 00491 } 00492 00493 if (!possible_match) { 00494 return 0; 00495 } 00496 00497 if (!strcmp(core_instance->agent->device_name, name)) { 00498 return CMP_MATCH | CMP_STOP; 00499 } 00500 return 0; 00501 }
static const char* monitor_policy_to_str | ( | enum ast_cc_monitor_policies | policy | ) | [static] |
Definition at line 625 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().
00626 { 00627 switch (policy) { 00628 case AST_CC_MONITOR_NEVER: 00629 return "never"; 00630 case AST_CC_MONITOR_NATIVE: 00631 return "native"; 00632 case AST_CC_MONITOR_GENERIC: 00633 return "generic"; 00634 case AST_CC_MONITOR_ALWAYS: 00635 return "always"; 00636 default: 00637 /* This should never happen... */ 00638 return ""; 00639 } 00640 }
static int offer_timer_expire | ( | const void * | data | ) | [static] |
Definition at line 2418 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().
02419 { 02420 struct ast_cc_agent *agent = (struct ast_cc_agent *) data; 02421 struct cc_generic_agent_pvt *agent_pvt = agent->private_data; 02422 ast_log_dynamic_level(cc_logger_level, "Core %d: Queuing change request because offer timer has expired.\n", 02423 agent->core_id); 02424 agent_pvt->offer_timer_id = -1; 02425 ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name); 02426 cc_unref(agent, "Remove scheduler's reference to the agent"); 02427 return 0; 02428 }
static int print_stats_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4150 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().
04151 { 04152 int *cli_fd = arg; 04153 struct cc_core_instance *core_instance = obj; 04154 04155 ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name, 04156 cc_state_to_string(core_instance->current_state)); 04157 AST_LIST_LOCK(core_instance->monitors); 04158 cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0); 04159 AST_LIST_UNLOCK(core_instance->monitors); 04160 return 0; 04161 }
static void request_cc | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2809 of file ccss.c.
References cc_core_instance::agent, AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, has_device_monitors(), ast_cc_monitor::interface, manager_event, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor_callbacks::request_cc.
Referenced by cc_caller_requested().
02810 { 02811 struct ast_cc_monitor *monitor_iter; 02812 AST_LIST_LOCK(core_instance->monitors); 02813 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02814 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02815 if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) { 02816 AST_LIST_REMOVE_CURRENT(next); 02817 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02818 monitor_iter->interface->device_name, 1); 02819 cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor"); 02820 } else { 02821 manager_event(EVENT_FLAG_CC, "CCRequested", 02822 "CoreID: %d\r\n" 02823 "Caller: %s\r\n" 02824 "Callee: %s\r\n", 02825 core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name); 02826 } 02827 } 02828 } 02829 AST_LIST_TRAVERSE_SAFE_END; 02830 02831 if (!has_device_monitors(core_instance)) { 02832 ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC"); 02833 } 02834 AST_LIST_UNLOCK(core_instance->monitors); 02835 }
static enum ast_cc_agent_policies str_to_agent_policy | ( | const char *const | value | ) | [static] |
Definition at line 580 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().
00581 { 00582 if (!strcasecmp(value, "never")) { 00583 return AST_CC_AGENT_NEVER; 00584 } else if (!strcasecmp(value, "native")) { 00585 return AST_CC_AGENT_NATIVE; 00586 } else if (!strcasecmp(value, "generic")) { 00587 return AST_CC_AGENT_GENERIC; 00588 } else { 00589 ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value); 00590 return AST_CC_AGENT_NEVER; 00591 } 00592 }
static enum ast_cc_monitor_policies str_to_monitor_policy | ( | const char *const | value | ) | [static] |
Definition at line 594 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().
00595 { 00596 if (!strcasecmp(value, "never")) { 00597 return AST_CC_MONITOR_NEVER; 00598 } else if (!strcasecmp(value, "native")) { 00599 return AST_CC_MONITOR_NATIVE; 00600 } else if (!strcasecmp(value, "generic")) { 00601 return AST_CC_MONITOR_GENERIC; 00602 } else if (!strcasecmp(value, "always")) { 00603 return AST_CC_MONITOR_ALWAYS; 00604 } else { 00605 ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value); 00606 return AST_CC_MONITOR_NEVER; 00607 } 00608 }
static void suspend | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2904 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor_callbacks::suspend.
Referenced by build_suspend(), cc_caller_busy(), and handle_controlstreamfile().
02905 { 02906 struct ast_cc_monitor *monitor_iter; 02907 AST_LIST_LOCK(core_instance->monitors); 02908 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02909 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02910 if (monitor_iter->callbacks->suspend(monitor_iter)) { 02911 AST_LIST_REMOVE_CURRENT(next); 02912 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02913 monitor_iter->interface->device_name, 1); 02914 cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor"); 02915 } 02916 } 02917 } 02918 AST_LIST_TRAVERSE_SAFE_END; 02919 02920 if (!has_device_monitors(core_instance)) { 02921 ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC"); 02922 } 02923 AST_LIST_UNLOCK(core_instance->monitors); 02924 }
static void unsuspend | ( | struct cc_core_instance * | core_instance | ) | [static] |
Definition at line 2851 of file ccss.c.
References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, cc_monitor_backend::next, and ast_cc_monitor_callbacks::unsuspend.
Referenced by cc_active().
02852 { 02853 struct ast_cc_monitor *monitor_iter; 02854 AST_LIST_LOCK(core_instance->monitors); 02855 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) { 02856 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) { 02857 if (monitor_iter->callbacks->unsuspend(monitor_iter)) { 02858 AST_LIST_REMOVE_CURRENT(next); 02859 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id, 02860 monitor_iter->interface->device_name, 1); 02861 cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor"); 02862 } 02863 } 02864 } 02865 AST_LIST_TRAVERSE_SAFE_END; 02866 02867 if (!has_device_monitors(core_instance)) { 02868 ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC"); 02869 } 02870 AST_LIST_UNLOCK(core_instance->monitors); 02871 }
struct ast_cli_entry cc_cli[] [static] |
Initial value:
{ { .handler = handle_cc_status , .summary = "Reports CC stats" ,__VA_ARGS__ }, { .handler = handle_cc_kill , .summary = "Kill a CC transaction" ,__VA_ARGS__ }, }
Definition at line 4293 of file ccss.c.
Referenced by ast_cc_init().
struct ao2_container* cc_core_instances [static] |
Definition at line 313 of file ccss.c.
Referenced by ast_cc_agent_callback(), ast_cc_init(), ast_cc_monitor_count(), cc_cli_output_status(), cc_complete(), cc_core_init_instance(), cc_failed(), cccancel_exec(), ccreq_exec(), complete_core_id(), count_agents(), find_cc_core_instance(), handle_cc_kill(), and kill_duplicate_offers().
const int CC_CORE_INSTANCES_BUCKETS = 17 [static] |
struct ast_taskprocessor* cc_core_taskprocessor [static] |
Taskprocessor from which all CC agent and monitor callbacks are called.
Definition at line 112 of file ccss.c.
Referenced by ast_cc_agent_status_response(), ast_cc_init(), ast_cc_monitor_failed(), ast_cc_monitor_party_b_free(), ast_cc_monitor_status_request(), ast_cc_monitor_stop_ringing(), cc_request_state_change(), generic_agent_devstate_cb(), generic_monitor_devstate_cb(), and handle_cc_status().
struct ast_cc_config_params cc_default_params [static] |
int cc_logger_level [static] |
const char* CC_LOGGER_LEVEL_NAME = "CC" [static] |
int cc_request_count [static] |
struct ast_sched_thread* cc_sched_thread [static] |
The sched_thread ID used for all generic CC timeouts
Definition at line 102 of file ccss.c.
Referenced by ast_cc_init(), cc_generic_agent_start_offer_timer(), cc_generic_agent_stop_offer_timer(), cc_generic_monitor_cancel_available_timer(), and cc_generic_monitor_request_cc().
struct { ... } cc_service_to_string_map[] [static] |
Referenced by cc_service_to_string().
struct { ... } cc_state_to_string_map[] [static] |
Referenced by cc_state_to_string().
const char* cccancel_app = "CallCompletionCancel" [static] |
int core_id_counter [static] |
int dialed_cc_interface_counter [static] |
struct ast_datastore_info dialed_cc_interfaces_info [static] |
Initial value:
{ .type = "Dial CC Interfaces", .duplicate = dialed_cc_interfaces_duplicate, .destroy = dialed_cc_interfaces_destroy, }
Definition at line 1709 of file ccss.c.
Referenced by ast_cc_call_init(), ast_cc_extension_monitor_add_dialstring(), ast_cc_get_current_core_id(), ast_cc_offer(), ast_handle_cc_control_frame(), ast_ignore_cc(), cc_build_payload(), and cc_interfaces_datastore_init().
struct ast_cc_agent_callbacks generic_agent_callbacks [static] |
struct ast_cc_monitor_callbacks generic_monitor_cbs [static] |
struct ao2_container* generic_monitors |
Definition at line 1040 of file ccss.c.
Referenced by ast_cc_init(), cc_generic_monitor_destructor(), create_new_generic_list(), and find_generic_monitor_instance_list().
unsigned int global_cc_max_requests [static] |
struct ast_datastore_info recall_ds_info [static] |
Initial value:
{ .type = "cc_recall", .duplicate = cc_recall_ds_duplicate, .destroy = cc_recall_ds_destroy, }
Definition at line 3118 of file ccss.c.
Referenced by ast_cc_agent_set_interfaces_chanvar(), ast_cc_completed(), ast_cc_is_recall(), ast_ignore_cc(), ast_set_cc_interfaces_chanvar(), and ast_setup_cc_recall_datastore().
const char* service_string |
int(* const[]) state_change_funcs(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state) [static] |
const char* state_string |