Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Enumerations | Functions | Variables
ccss.c File Reference

Call Completion Supplementary Services implementation. More...

#include "asterisk.h"
#include "asterisk/astobj2.h"
#include "asterisk/strings.h"
#include "asterisk/ccss.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/devicestate.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/stasis_system.h"
#include "asterisk/format_cache.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...
 

Macros

#define CC_ACTIVE_DEVSTATE_DEFAULT   AST_DEVICE_INUSE
 
#define CC_AVAILABLE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE
 
#define CC_CALLEE_READY_DEVSTATE_DEFAULT   AST_DEVICE_RINGING
 
#define CC_CALLER_BUSY_DEVSTATE_DEFAULT   AST_DEVICE_ONHOLD
 
#define CC_CALLER_OFFERED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE
 
#define CC_CALLER_REQUESTED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE
 
#define CC_COMPLETE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE
 
#define CC_FAILED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE
 
#define CC_MAX_AGENTS_DEFAULT   5
 
#define CC_MAX_MONITORS_DEFAULT   5
 
#define CC_OFFER_TIMER_DEFAULT   20 /* Seconds */
 
#define CC_RECALL_TIMER_DEFAULT   20 /* Seconds */
 
#define CC_RECALLING_DEVSTATE_DEFAULT   AST_DEVICE_RINGING
 
#define CCBS_AVAILABLE_TIMER_DEFAULT   4800 /* Seconds */
 
#define CCNR_AVAILABLE_TIMER_DEFAULT   7200 /* Seconds */
 
#define GLOBAL_CC_MAX_REQUESTS_DEFAULT   20
 

Enumerations

enum  cc_state {
  CC_AVAILABLE, CC_CALLER_OFFERED, CC_CALLER_REQUESTED, CC_ACTIVE,
  CC_CALLEE_READY, CC_CALLER_BUSY, CC_RECALLING, CC_COMPLETE,
  CC_FAILED
}
 The states used in the CCSS core state machine. More...
 
enum  match_flags { MATCH_NO_REQUEST = (1 << 0), MATCH_REQUEST = (1 << 1) }
 

Functions

struct ast_cc_config_params__ast_cc_config_params_init (const char *file, int line, const char *function)
 Allocate and initialize an ast_cc_config_params structure. More...
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
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. More...
 
struct ast_cc_agentast_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. More...
 
int ast_cc_agent_caller_available (int core_id, const char *const debug,...)
 Indicate that a previously unavailable caller has become available. More...
 
int ast_cc_agent_caller_busy (int core_id, const char *debug,...)
 Indicate that the caller is busy. More...
 
int ast_cc_agent_recalling (int core_id, const char *const debug,...)
 Tell the CC core that a caller is currently recalling. More...
 
int ast_cc_agent_register (const struct ast_cc_agent_callbacks *callbacks)
 Register a set of agent callbacks with the core. More...
 
int ast_cc_agent_set_interfaces_chanvar (struct ast_channel *chan)
 Set the first level CC_INTERFACES channel variable for a channel. More...
 
int ast_cc_agent_status_response (int core_id, enum ast_device_state devstate)
 Response with a caller's current status. More...
 
void ast_cc_agent_unregister (const struct ast_cc_agent_callbacks *callbacks)
 Unregister a set of agent callbacks with the core. More...
 
int ast_cc_available_timer_expire (const void *data)
 Scheduler callback for available timer expiration. More...
 
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. More...
 
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. More...
 
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. More...
 
int ast_cc_call_init (struct ast_channel *chan, int *ignore_cc)
 Start the CC process on a call. More...
 
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. More...
 
int ast_cc_completed (struct ast_channel *chan, const char *const debug,...)
 Indicate recall has been acknowledged. More...
 
void ast_cc_config_params_destroy (struct ast_cc_config_params *params)
 Free memory from CCSS configuration params. More...
 
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 More...
 
void ast_cc_default_config_params (struct ast_cc_config_params *params)
 Set the specified CC config params to default values. More...
 
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. More...
 
int ast_cc_failed (int core_id, const char *const debug,...)
 Indicate failure has occurred. More...
 
int ast_cc_get_current_core_id (struct ast_channel *chan)
 Get the core id for the current call. More...
 
struct ast_cc_monitorast_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. More...
 
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 More...
 
int ast_cc_is_config_param (const char *const name)
 Is this a CCSS configuration parameter? More...
 
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. More...
 
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. More...
 
int ast_cc_monitor_count (const char *const name, const char *const type)
 Return the number of outstanding CC requests to a specific device. More...
 
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. More...
 
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. More...
 
int ast_cc_monitor_register (const struct ast_cc_monitor_callbacks *callbacks)
 Register a set of monitor callbacks with the core. More...
 
int ast_cc_monitor_request_acked (int core_id, const char *const debug,...)
 Indicate that an outbound entity has accepted our CC request. More...
 
int ast_cc_monitor_status_request (int core_id)
 Request the status of a caller or callers. More...
 
int ast_cc_monitor_stop_ringing (int core_id)
 Alert a caller to stop ringing. More...
 
void ast_cc_monitor_unregister (const struct ast_cc_monitor_callbacks *callbacks)
 Unregister a set of monitor callbacks with the core. More...
 
int ast_cc_offer (struct ast_channel *caller_chan)
 Offer CC to a caller. More...
 
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. More...
 
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 More...
 
const char * ast_get_cc_agent_dialstring (struct ast_cc_config_params *config)
 Get the cc_agent_dialstring. More...
 
enum ast_cc_agent_policies ast_get_cc_agent_policy (struct ast_cc_config_params *config)
 Get the cc_agent_policy. More...
 
const char * ast_get_cc_callback_sub (struct ast_cc_config_params *config)
 Get the name of the callback subroutine. More...
 
unsigned int ast_get_cc_max_agents (struct ast_cc_config_params *config)
 Get the cc_max_agents. More...
 
unsigned int ast_get_cc_max_monitors (struct ast_cc_config_params *config)
 Get the cc_max_monitors. More...
 
enum ast_cc_monitor_policies ast_get_cc_monitor_policy (struct ast_cc_config_params *config)
 Get the cc_monitor_policy. More...
 
unsigned int ast_get_cc_offer_timer (struct ast_cc_config_params *config)
 Get the cc_offer_timer. More...
 
unsigned int ast_get_cc_recall_timer (struct ast_cc_config_params *config)
 Get the cc_recall_timer. More...
 
unsigned int ast_get_ccbs_available_timer (struct ast_cc_config_params *config)
 Get the ccbs_available_timer. More...
 
unsigned int ast_get_ccnr_available_timer (struct ast_cc_config_params *config)
 Get the ccnr_available_timer. More...
 
void ast_handle_cc_control_frame (struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
 Properly react to a CC control frame. More...
 
void ast_ignore_cc (struct ast_channel *chan)
 Mark the channel to ignore further CC activity. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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. More...
 
void ast_set_cc_agent_dialstring (struct ast_cc_config_params *config, const char *const value)
 Set the cc_agent_dialstring. More...
 
int ast_set_cc_agent_policy (struct ast_cc_config_params *config, enum ast_cc_agent_policies value)
 Set the cc_agent_policy. More...
 
void ast_set_cc_callback_sub (struct ast_cc_config_params *config, const char *const value)
 Set the callback subroutine name. More...
 
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. More...
 
void ast_set_cc_max_agents (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_max_agents. More...
 
void ast_set_cc_max_monitors (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_max_monitors. More...
 
int ast_set_cc_monitor_policy (struct ast_cc_config_params *config, enum ast_cc_monitor_policies value)
 Set the cc_monitor_policy. More...
 
void ast_set_cc_offer_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_offer_timer. More...
 
void ast_set_cc_recall_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_recall_timer. More...
 
void ast_set_ccbs_available_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the ccbs_available_timer. More...
 
void ast_set_ccnr_available_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the ccnr_available_timer. More...
 
int ast_setup_cc_recall_datastore (struct ast_channel *chan, const int core_id)
 Set up a CC recall datastore on a channel. More...
 
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_agentcc_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_instancecc_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_monitorcc_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_monitorcc_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 int cc_publish (struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
 
static void cc_publish_available (int core_id, const char *callee, const char *service)
 
static void cc_publish_callerrecalling (int core_id, const char *caller)
 
static void cc_publish_callerstartmonitoring (int core_id, const char *caller)
 
static void cc_publish_callerstopmonitoring (int core_id, const char *caller)
 
static void cc_publish_failure (int core_id, const char *caller, const char *reason)
 
static void cc_publish_monitorfailed (int core_id, const char *callee)
 
static void cc_publish_offertimerstart (int core_id, const char *caller, unsigned int expires)
 
static void cc_publish_recallcomplete (int core_id, const char *caller)
 
static void cc_publish_requestacknowledged (int core_id, const char *caller)
 
static void cc_publish_requested (int core_id, const char *caller, const char *callee)
 
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 enum ast_device_state cc_state_to_devstate (enum cc_state state)
 
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 enum ast_device_state ccss_device_state (const char *device_name)
 
static void ccss_notify_device_state_change (const char *device, enum cc_state state)
 
static void check_callback_sanity (const struct ast_cc_agent_callbacks *callbacks)
 
static char * complete_core_id (const char *word)
 
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_listcreate_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_pvtextension_monitor_pvt_init (void)
 
static const struct ast_cc_agent_callbacksfind_agent_callbacks (struct ast_channel *chan)
 
static struct cc_core_instancefind_cc_core_instance (const int core_id)
 
static struct generic_monitor_instance_listfind_generic_monitor_instance_list (const char *const device_name)
 
static const struct ast_cc_monitor_callbacksfind_monitor_callbacks (const char *const type)
 
static void generic_agent_devstate_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static void generic_monitor_devstate_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static int generic_monitor_devstate_tp_cb (void *data)
 
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 More...
 
static void initialize_cc_devstate_map (void)
 
static void initialize_cc_devstate_map_helper (struct ast_config *cc_config, enum cc_state state, const char *cc_setting)
 
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 load_module (void)
 
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 int unload_module (void)
 
static void unsuspend (struct cc_core_instance *core_instance)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Call Completion Supplementary Services" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "da6642af068ee5e6490c5b1d2cc1d238" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
struct cc_agent_backends cc_agent_backends = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct ast_cli_entry cc_cli []
 
static struct ao2_containercc_core_instances
 
static const int CC_CORE_INSTANCES_BUCKETS = 17
 
static struct ast_taskprocessorcc_core_taskprocessor
 
static const struct ast_cc_config_params cc_default_params
 
static int cc_logger_level
 
static const char * CC_LOGGER_LEVEL_NAME = "CC"
 
struct cc_monitor_backends cc_monitor_backends = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static int cc_request_count
 
static struct ast_sched_contextcc_sched_context
 
struct {
   enum ast_cc_service_type   service
 
   const char *   service_string
 
cc_service_to_string_map []
 
static enum ast_device_state cc_state_to_devstate_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 const struct ast_datastore_info dialed_cc_interfaces_info
 
static struct ast_cc_agent_callbacks generic_agent_callbacks
 
static struct ast_cc_monitor_callbacks generic_monitor_cbs
 
struct ao2_containergeneric_monitors
 
static unsigned int global_cc_max_requests
 
static const 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)
 

Detailed Description

Call Completion Supplementary Services implementation.

Author
Mark Michelson mmich.nosp@m.elso.nosp@m.n@dig.nosp@m.ium..nosp@m.com

Definition in file ccss.c.

Enumeration Type Documentation

enum cc_state

The states used in the CCSS core state machine.

Since
1.8 For more information, see doc/CCSS_architecture.pdf
Enumerator
CC_AVAILABLE 

Entered when it is determined that CCSS may be used for the call

CC_CALLER_OFFERED 

Entered when a CCSS agent has offered CCSS to a caller

CC_CALLER_REQUESTED 

Entered when a CCSS agent confirms that a caller has requested CCSS

CC_ACTIVE 

Entered when a CCSS monitor confirms acknowledgment of an outbound CCSS request

CC_CALLEE_READY 

Entered when a CCSS monitor alerts the core that the called party has become available

CC_CALLER_BUSY 

Entered when a CCSS agent alerts the core that the calling party may not be recalled because he is unavailable

CC_RECALLING 

Entered when a CCSS agent alerts the core that the calling party is attempting to recall the called party

CC_COMPLETE 

Entered when an application alerts the core that the calling party's recall attempt has had a call progress response indicated

CC_FAILED 

Entered any time that something goes wrong during the process, thus resulting in the failure of the attempted CCSS transaction. Note also that cancellations of CC are treated as failures.

Definition at line 180 of file ccss.c.

180  {
181  /*! Entered when it is determined that CCSS may be used for the call */
182  CC_AVAILABLE,
183  /*! Entered when a CCSS agent has offered CCSS to a caller */
185  /*! Entered when a CCSS agent confirms that a caller has
186  * requested CCSS */
188  /*! Entered when a CCSS monitor confirms acknowledgment of an
189  * outbound CCSS request */
190  CC_ACTIVE,
191  /*! Entered when a CCSS monitor alerts the core that the called party
192  * has become available */
194  /*! Entered when a CCSS agent alerts the core that the calling party
195  * may not be recalled because he is unavailable
196  */
198  /*! Entered when a CCSS agent alerts the core that the calling party
199  * is attempting to recall the called party
200  */
201  CC_RECALLING,
202  /*! Entered when an application alerts the core that the calling party's
203  * recall attempt has had a call progress response indicated
204  */
205  CC_COMPLETE,
206  /*! Entered any time that something goes wrong during the process, thus
207  * resulting in the failure of the attempted CCSS transaction. Note also
208  * that cancellations of CC are treated as failures.
209  */
210  CC_FAILED,
211 };

Function Documentation

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.

Note
Reasonable default values are chosen for the parameters upon allocation.
Return values
NULLUnable to allocate the structure
non-NULLA pointer to the newly allocated and initialized structure

Definition at line 680 of file ccss.c.

References ast_cc_default_config_params().

681 {
682  struct ast_cc_config_params *params = __ast_malloc(sizeof(*params), file, line, function);
683 
684  if (!params) {
685  return NULL;
686  }
687 
689  return params;
690 }
void ast_cc_default_config_params(struct ast_cc_config_params *params)
Set the specified CC config params to default values.
Definition: ccss.c:675
int ast_cc_agent_accept_request ( int  core_id,
const char *const  debug,
  ... 
)

Accept inbound CC request.

Since
1.8

When a caller requests CC, this function should be called to let the core know that the request has been accepted.

Parameters
core_idcore_id of the CC transaction
debugoptional string to print for debugging purposes
Return values
0Success
-1Failure

Definition at line 3741 of file ccss.c.

References CC_CALLER_REQUESTED.

3742 {
3743  va_list ap;
3744  int res;
3745 
3746  va_start(ap, debug);
3747  res = cc_request_state_change(CC_CALLER_REQUESTED, core_id, debug, ap);
3748  va_end(ap);
3749  return res;
3750 }
static int debug
Global debug status.
Definition: res_xmpp.c:441
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.

Note
Since agents are refcounted, and this function returns a reference to the agent, it is imperative that you decrement the refcount of the agent once you have finished using it.
Parameters
flagsastobj2 search flags
functionan ao2 callback function to call
argthe argument to the callback function
typeThe type of agents to call the callback on

Definition at line 456 of file ccss.c.

References cc_core_instance::agent.

457 {
458  struct cc_callback_helper helper = {.function = function, .args = args, .type = type};
459  struct cc_core_instance *core_instance;
460  if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper,
461  "Calling provided agent callback function"))) {
462  struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent");
463  cc_unref(core_instance, "agent callback done with the core_instance");
464  return agent;
465  }
466  return NULL;
467 }
struct ast_cc_agent * agent
Definition: ccss.c:340
int ast_cc_agent_caller_available ( int  core_id,
const char *const  debug,
  ... 
)

Indicate that a previously unavailable caller has become available.

Since
1.8

If a monitor is suspended due to a caller becoming unavailable, then this function should be called to indicate that the caller has become available.

Parameters
core_idcore_id of the CC transaction
debugoptional string to print for debugging purposes
Return values
0Success
-1Failure

Definition at line 3785 of file ccss.c.

References CC_ACTIVE.

3786 {
3787  va_list ap;
3788  int res;
3789 
3790  va_start(ap, debug);
3791  res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3792  va_end(ap);
3793  return res;
3794 }
static int debug
Global debug status.
Definition: res_xmpp.c:441
unsigned int core_id
Definition: ccss.h:812
int ast_cc_agent_caller_busy ( int  core_id,
const char *const  debug,
  ... 
)

Indicate that the caller is busy.

Since
1.8

When the callee makes it known that he is available, the core will let the caller's channel driver know that it may attempt to let the caller know to attempt a recall. If the channel driver can detect, though, that the caller is busy, then the channel driver should call this function to let the CC core know.

Parameters
core_idcore_id of the CC transaction
debugoptional string to print for debugging purposes
Return values
0Success
-1Failure

Definition at line 3774 of file ccss.c.

References CC_CALLER_BUSY.

3775 {
3776  va_list ap;
3777  int res;
3778 
3779  va_start(ap, debug);
3780  res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap);
3781  va_end(ap);
3782  return res;
3783 }
static int debug
Global debug status.
Definition: res_xmpp.c:441
unsigned int core_id
Definition: ccss.h:812
int ast_cc_agent_recalling ( int  core_id,
const char *const  debug,
  ... 
)

Tell the CC core that a caller is currently recalling.

Since
1.8

The main purpose of this is so that the core can alert the monitor to stop its available timer since the caller has begun its recall phase.

Parameters
core_idcore_id of the CC transaction
debugoptional string to print for debugging purposes
Return values
0Success
-1Failure

Definition at line 3796 of file ccss.c.

References CC_RECALLING.

3797 {
3798  va_list ap;
3799  int res;
3800 
3801  va_start(ap, debug);
3802  res = cc_request_state_change(CC_RECALLING, core_id, debug, ap);
3803  va_end(ap);
3804  return res;
3805 }
static int debug
Global debug status.
Definition: res_xmpp.c:441
unsigned int core_id
Definition: ccss.h:812
int ast_cc_agent_register ( const struct ast_cc_agent_callbacks callbacks)

Register a set of agent callbacks with the core.

Since
1.8

This is made so that at agent creation time, the proper callbacks may be installed and the proper .init callback may be called for the monitor to establish private data.

Parameters
callbacksThe callbacks used by the agent implementation
Return values
0Successfully registered
-1Failure to register

Definition at line 1217 of file ccss.c.

References ast_calloc, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module().

1218 {
1219  struct cc_agent_backend *backend = ast_calloc(1, sizeof(*backend));
1220 
1221  if (!backend) {
1222  return -1;
1223  }
1224 
1225  backend->callbacks = callbacks;
1227  AST_RWLIST_INSERT_TAIL(&cc_agent_backends, backend, next);
1229  return 0;
1230 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
int ast_cc_agent_set_interfaces_chanvar ( struct ast_channel chan)

Set the first level CC_INTERFACES channel variable for a channel.

Since
1.8
Note
Implementers of protocol-specific CC agents should call this function after calling ast_setup_cc_recall_datastore.
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.

The CC_INTERFACES channel variable will have the interfaces that should be called back for a specific PBX instance.

Parameters
chanThe channel to set the CC_INTERFACES variable on

Definition at line 3596 of file ccss.c.

References ast_channel_datastore_find(), AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_str_buffer(), ast_str_create, cc_logger_level, ast_datastore::data, and pbx_builtin_setvar_helper().

3597 {
3598  struct ast_datastore *recall_datastore;
3599  struct cc_monitor_tree *interface_tree;
3600  struct ast_cc_monitor *monitor;
3601  struct cc_recall_ds_data *recall_data;
3602  struct ast_str *str = ast_str_create(64);
3603  int core_id;
3604 
3605  if (!str) {
3606  return -1;
3607  }
3608 
3609  ast_channel_lock(chan);
3610  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3611  ast_channel_unlock(chan);
3612  ast_free(str);
3613  return -1;
3614  }
3615  recall_data = recall_datastore->data;
3616  interface_tree = recall_data->interface_tree;
3617  core_id = recall_data->core_id;
3618  ast_channel_unlock(chan);
3619 
3620  AST_LIST_LOCK(interface_tree);
3621  monitor = AST_LIST_FIRST(interface_tree);
3622  build_cc_interfaces_chanvar(monitor, &str);
3623  AST_LIST_UNLOCK(interface_tree);
3624 
3625  pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3626  ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3627  core_id, ast_str_buffer(str));
3628 
3629  ast_free(str);
3630  return 0;
3631 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
Support for dynamic strings.
Definition: strings.h:623
The "tree" of interfaces that is dialed.
Definition: ccss.c:323
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void * data
Definition: datastore.h:66
static int cc_logger_level
Definition: ccss.c:133
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
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.

Parameters
core_idThe core ID of the CC transaction
devstateThe current state of the caller to which the agent pertains
Return values
0Successfully responded with our status
-1Failed to respond with our status

Definition at line 4058 of file ccss.c.

References ast_calloc, and ast_taskprocessor_push().

4059 {
4060  struct cc_status_response_args *args;
4061  struct cc_core_instance *core_instance;
4062  int res;
4063 
4064  args = ast_calloc(1, sizeof(*args));
4065  if (!args) {
4066  return -1;
4067  }
4068 
4069  core_instance = find_cc_core_instance(core_id);
4070  if (!core_instance) {
4071  ast_free(args);
4072  return -1;
4073  }
4074 
4075  args->core_instance = core_instance;
4076  args->devstate = devstate;
4077 
4078  res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_response, args);
4079  if (res) {
4080  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4081  ast_free(args);
4082  }
4083  return res;
4084 }
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125
void ast_cc_agent_unregister ( const struct ast_cc_agent_callbacks callbacks)

Unregister a set of agent callbacks with the core.

Since
1.8

If a module which makes use of a CC agent is unloaded, then it may unregister its agent callbacks with the core.

Parameters
callbacksThe callbacks used by the agent implementation

Definition at line 1232 of file ccss.c.

References AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

1233 {
1234  struct cc_agent_backend *backend;
1236  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_agent_backends, backend, next) {
1237  if (backend->callbacks == callbacks) {
1238  AST_RWLIST_REMOVE_CURRENT(next);
1239  ast_free(backend);
1240  break;
1241  }
1242  }
1243  AST_RWLIST_TRAVERSE_SAFE_END;
1245 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
int ast_cc_available_timer_expire ( const void *  data)

Scheduler callback for available timer expiration.

Since
1.8
Note
When arming the available timer from within a device monitor, you MUST use this function as the callback for the scheduler.
Parameters
dataA reference to the CC monitor on which the timer was running.

Definition at line 1487 of file ccss.c.

References ast_cc_monitor_failed(), ast_cc_monitor::available_timer_id, ast_cc_monitor::core_id, and ast_cc_monitor::interface.

1488 {
1489  struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data;
1490  int res;
1491  monitor->available_timer_id = -1;
1492  res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor");
1493  cc_unref(monitor, "Unref reference from scheduler\n");
1494  return res;
1495 }
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.
Definition: ccss.c:3906
int core_id
Definition: ccss.h:494
struct ast_cc_interface * interface
Definition: ccss.h:480
int available_timer_id
Definition: ccss.h:513
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.

Since
1.8

chan_dahdi is weird. It doesn't seem to actually queue frames when it needs to tell an application something. Instead it wakes up, tells the application that it has data ready, and then based on set flags, creates the proper frame type. For chan_dahdi, we provide this function. It provides us the data we need, and we'll make its frame for it.

Parameters
chanA channel involved in the call. What we want is on a datastore on both incoming and outgoing so either may be provided
cc_paramsThe CC configuration parameters for the outbound target
monitor_typeThe type of monitor to use when CC is requested
device_nameThe name of the outbound target device.
dialstringThe dial string used when calling this specific interface
serviceWhat kind of CC service is being offered. (CCBS/CCNR/etc...)
private_dataIf 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]frameThe 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.
Return values
-1Failure. At some point there was a failure. Do not attempt to use the frame in this case.
0Success

Definition at line 4141 of file ccss.c.

References ast_calloc, AST_CONTROL_CC, AST_FRAME_CONTROL, AST_MALLOCD_DATA, ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, and ast_frame::subclass.

Referenced by ast_queue_cc_frame().

4145 {
4146  struct cc_control_payload *payload = ast_calloc(1, sizeof(*payload));
4147 
4148  if (!payload) {
4149  return -1;
4150  }
4151  if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) {
4152  /* Something screwed up, we can't make a frame with this */
4153  ast_free(payload);
4154  return -1;
4155  }
4156  frame->frametype = AST_FRAME_CONTROL;
4157  frame->subclass.integer = AST_CONTROL_CC;
4158  frame->data.ptr = payload;
4159  frame->datalen = sizeof(*payload);
4160  frame->mallocd = AST_MALLOCD_DATA;
4161  return 0;
4162 }
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:221
void * private_data
Private data allocated by the callee.
Definition: ccss.c:256
#define AST_MALLOCD_DATA
struct ast_frame_subclass subclass
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:292
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:304
enum ast_cc_service_type service
Service offered by the endpoint.
Definition: ccss.c:265
union ast_frame::@224 data
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:239
enum ast_frame_type frametype
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.

Since
1.8
Parameters
inboundIncoming asterisk channel.
cc_paramsThe CC configuration parameters for the outbound target
monitor_typeThe type of monitor to use when CC is requested
device_nameThe name of the outbound target device.
dialstringThe dial string used when calling this specific interface
private_dataIf a native monitor is being used, and some channel-driver-specific private data has been allocated, then this parameter should contain a pointer to that data. If using a generic monitor, this parameter should remain NULL. Note that if this function should fail at some point, it is the responsibility of the caller to free the private data upon return.

For channel types that fail ast_request when the device is busy, we call into the channel driver with ast_cc_callback. This is the callback that is called in that case for each device found which could have been returned by ast_request.

This function creates a CC control frame payload, simulating the act of reading it from the nonexistent outgoing channel's frame queue. We then handle this simulated frame just as we would a normal CC frame which had actually been queued by the channel driver.

Definition at line 4197 of file ccss.c.

References ast_handle_cc_control_frame().

Referenced by dial_exec_full().

4199 {
4200  struct cc_control_payload payload;
4201  if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) {
4202  /* Something screwed up. Don't try to handle this payload */
4203  call_destructor_with_no_monitor(monitor_type, private_data);
4204  return;
4205  }
4206  ast_handle_cc_control_frame(inbound, NULL, &payload);
4207 }
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:221
void * private_data
Private data allocated by the callee.
Definition: ccss.c:256
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:292
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:304
void ast_handle_cc_control_frame(struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
Properly react to a CC control frame.
Definition: ccss.c:2293
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:239
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.

Since
1.8 In some situations, notably if a call-limit is reached in SIP, ast_call will fail due to Asterisk's knowing that the desired device is currently busy. In such a situation, CCBS should be made available to the caller.

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 4164 of file ccss.c.

References 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(), and ast_handle_cc_control_frame().

Referenced by dial_exec_full().

4165 {
4167  struct cc_control_payload payload;
4168  struct ast_cc_config_params *cc_params;
4169 
4170  if (ast_channel_hangupcause(outgoing) != AST_CAUSE_BUSY && ast_channel_hangupcause(outgoing) != AST_CAUSE_CONGESTION) {
4171  /* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call
4172  * failing is something other than busy or congestion
4173  */
4174  return;
4175  }
4176 
4177  cc_params = ast_channel_get_cc_config_params(outgoing);
4178  if (!cc_params) {
4179  return;
4180  }
4182  /* This sort of CCBS only works if using generic CC. For native, we would end up sending
4183  * a CC request for a non-existent call. The far end will reject this every time
4184  */
4185  return;
4186  }
4187 
4188  ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
4189  if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
4190  dialstring, AST_CC_CCBS, NULL, &payload)) {
4191  /* Something screwed up, we can't make a frame with this */
4192  return;
4193  }
4194  ast_handle_cc_control_frame(incoming, outgoing, &payload);
4195 }
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:221
struct ast_cc_config_params * ast_channel_get_cc_config_params(struct ast_channel *chan)
Get the CCSS parameters from a channel.
Definition: channel.c:10474
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:876
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:292
void ast_handle_cc_control_frame(struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
Properly react to a CC control frame.
Definition: ccss.c:2293
#define AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:455
#define AST_CHANNEL_NAME
Definition: channel.h:171
int ast_channel_get_device_name(struct ast_channel *chan, char *device_name, size_t name_buffer_length)
Get a device name given its channel structure.
Definition: channel.c:10496
int ast_cc_call_init ( struct ast_channel chan,
int *  ignore_cc 
)

Start the CC process on a call.

Since
1.8

Whenever a CC-capable application, such as Dial, wishes to engage in CC activity, it initiates the process by calling this function. If the CC core should discover that a previous application has called ast_ignore_cc on this channel or a "parent" channel, then the value of the ignore_cc integer passed in will be set nonzero.

The ignore_cc parameter is a convenience parameter. It can save an application the trouble of trying to call CC APIs when it knows that it should just ignore further attempts at CC actions.

Parameters
chanThe inbound channel calling the CC-capable application.
[out]ignore_ccWill be set non-zero if no further CC actions need to be taken
Return values
0Success
-1Failure

Definition at line 2386 of file ccss.c.

References AST_CC_AGENT_NEVER, ast_channel_datastore_find(), ast_channel_get_cc_config_params(), ast_get_cc_agent_policy(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log_dynamic_level, cc_logger_level, ast_cc_monitor::core_id, dialed_cc_interfaces::core_id, ast_datastore::data, dialed_cc_interfaces::dial_parent_id, ast_cc_monitor::id, dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, and interfaces.

Referenced by dial_exec_full().

2387 {
2388  /* There are three situations to deal with here:
2389  *
2390  * 1. The channel does not have a dialed_cc_interfaces datastore on
2391  * it. This means that this is the first time that Dial has
2392  * been called. We need to create/initialize the datastore.
2393  *
2394  * 2. The channel does have a cc_interface datastore on it and
2395  * the "ignore" indicator is 0. This means that a Local channel
2396  * was called by a "parent" dial. We can check the datastore's
2397  * parent field to see who the root of this particular dial tree
2398  * is.
2399  *
2400  * 3. The channel does have a cc_interface datastore on it and
2401  * the "ignore" indicator is 1. This means that a second Dial call
2402  * is being made from an extension. In this case, we do not
2403  * want to make any additions/modifications to the datastore. We
2404  * will instead set a flag to indicate that CCSS is completely
2405  * disabled for this Dial attempt.
2406  */
2407 
2408  struct ast_datastore *cc_interfaces_datastore;
2410  struct ast_cc_monitor *monitor;
2411  struct ast_cc_config_params *cc_params;
2412 
2413  ast_channel_lock(chan);
2414 
2415  cc_params = ast_channel_get_cc_config_params(chan);
2416  if (!cc_params) {
2417  ast_channel_unlock(chan);
2418  return -1;
2419  }
2420  if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) {
2421  /* We can't offer CC to this caller anyway, so don't bother with CC on this call
2422  */
2423  *ignore_cc = 1;
2424  ast_channel_unlock(chan);
2425  ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", ast_channel_name(chan));
2426  return 0;
2427  }
2428 
2429  if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2430  /* Situation 1 has occurred */
2431  ast_channel_unlock(chan);
2432  return cc_interfaces_datastore_init(chan);
2433  }
2434  interfaces = cc_interfaces_datastore->data;
2435  ast_channel_unlock(chan);
2436 
2437  if (interfaces->ignore) {
2438  /* Situation 3 has occurred */
2439  *ignore_cc = 1;
2440  ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n");
2441  return 0;
2442  }
2443 
2444  /* Situation 2 has occurred */
2445  if (!(monitor = cc_extension_monitor_init(ast_channel_exten(chan),
2446  ast_channel_context(chan),
2447  interfaces->dial_parent_id))) {
2448  return -1;
2449  }
2450  monitor->core_id = interfaces->core_id;
2451  AST_LIST_LOCK(interfaces->interface_tree);
2452  cc_ref(monitor, "monitor tree's reference to the monitor");
2453  AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
2454  AST_LIST_UNLOCK(interfaces->interface_tree);
2455  interfaces->dial_parent_id = monitor->id;
2456  cc_unref(monitor, "Unref monitor's allocation reference");
2457  return 0;
2458 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
unsigned int id
Definition: ccss.h:485
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
struct ast_cc_config_params * ast_channel_get_cc_config_params(struct ast_channel *chan)
Get the CCSS parameters from a channel.
Definition: channel.c:10474
static struct ao2_container * interfaces
Container for registered format interfaces.
Definition: format.c:65
int core_id
Definition: ccss.h:494
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1907
void * data
Definition: datastore.h:66
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:859
unsigned int dial_parent_id
Definition: ccss.c:1880
static int cc_logger_level
Definition: ccss.c:133
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.

Since
1.8
Note
See the explanation in ast_channel_tech::cc_callback for more details.
Parameters
inbound
techChannel technology to use
destChannel/group/peer or whatever the specific technology uses
callbackFunction to call when a target is reached
Return values
0Always, I guess.

Definition at line 4209 of file ccss.c.

References ast_get_channel_tech(), and ast_channel_tech::cc_callback.

Referenced by dial_exec_full().

4210 {
4211  const struct ast_channel_tech *chantech = ast_get_channel_tech(tech);
4212 
4213  if (chantech && chantech->cc_callback) {
4214  chantech->cc_callback(inbound, dest, callback);
4215  }
4216 
4217  return 0;
4218 }
const struct ast_channel_tech * ast_get_channel_tech(const char *name)
Get a channel technology structure by name.
Definition: channel.c:592
int(* cc_callback)(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
Call a function with cc parameters as a function parameter.
Definition: channel.h:827
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:628
int ast_cc_completed ( struct ast_channel chan,
const char *const  debug,
  ... 
)

Indicate recall has been acknowledged.

Since
1.8

When we receive confirmation that an endpoint has responded to our CC recall, we call this function.

Parameters
chanThe inbound channel making the CC recall
debugoptional string to print for debugging purposes
Return values
0Success
-1Failure

Definition at line 3807 of file ccss.c.

References ast_channel_datastore_find(), CC_COMPLETE, and ast_datastore::data.

3808 {
3809  struct ast_datastore *recall_datastore;
3810  struct cc_recall_ds_data *recall_data;
3811  int core_id;
3812  va_list ap;
3813  int res;
3814 
3815  ast_channel_lock(chan);
3816  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3817  /* Silly! Why did you call this function if there's no recall DS? */
3818  ast_channel_unlock(chan);
3819  return -1;
3820  }
3821  recall_data = recall_datastore->data;
3822  if (recall_data->nested || recall_data->ignore) {
3823  /* If this is being called from a nested Dial, it is too
3824  * early to determine if the recall has actually completed.
3825  * The outermost dial is the only one with the authority to
3826  * declare the recall to be complete.
3827  *
3828  * Similarly, if this function has been called when the
3829  * recall has progressed beyond the first dial, this is not
3830  * a legitimate time to declare the recall to be done. In fact,
3831  * that should have been done already.
3832  */
3833  ast_channel_unlock(chan);
3834  return -1;
3835  }
3836  core_id = recall_data->core_id;
3837  ast_channel_unlock(chan);
3838  va_start(ap, debug);
3839  res = cc_request_state_change(CC_COMPLETE, core_id, debug, ap);
3840  va_end(ap);
3841  return res;
3842 }
static int debug
Global debug status.
Definition: res_xmpp.c:441
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
void * data
Definition: datastore.h:66
void ast_cc_config_params_destroy ( struct ast_cc_config_params params)

Free memory from CCSS configuration params.

Note
Just a call to ast_free for now...
Parameters
paramsPointer to structure whose memory we need to free

Definition at line 692 of file ccss.c.

Referenced by ast_channel_cc_params_init().

693 {
694  ast_free(params);
695 }
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

Since
1.8

For now, this is a simple memcpy, but this function is necessary since the size of an ast_cc_config_params structure is unknown outside of main/ccss.c. Also, this allows for easier expansion of the function in case it becomes more complex than just a memcpy.

Parameters
srcThe structure from which data is copied
destThe structure to which data is copied

Definition at line 854 of file ccss.c.

Referenced by ast_channel_cc_params_init(), and mkintf().

855 {
856  *dest = *src;
857 }
void ast_cc_default_config_params ( struct ast_cc_config_params params)

Set the specified CC config params to default values.

Since
1.8

This is just like ast_cc_copy_config_params() and could be used in place of it if you need to set the config params to defaults instead. You are simply "copying" defaults into the destination.

Parameters
paramsCC config params to set to default values.

Definition at line 675 of file ccss.c.

Referenced by __ast_cc_config_params_init().

676 {
677  *params = cc_default_params;
678 }
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.

Since
1.8

Whenever we request a channel, the parent extension monitor needs to store the dialstring of the device requested. The reason is so that we can call the device back during the recall even if we are not monitoring the device.

Parameters
incomingThe caller's channel
dialstringThe dialstring used when requesting the outbound channel
device_nameThe device name associated with the requested outbound channel

Definition at line 1983 of file ccss.c.

References ast_calloc, ast_channel_datastore_find(), ast_copy_string(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_datastore::data, extension_child_dialstring::device_name, dialed_cc_interfaces::dial_parent_id, ast_cc_monitor::id, dialed_cc_interfaces::interface_tree, extension_child_dialstring::is_valid, extension_child_dialstring::original_dialstring, and ast_cc_monitor::private_data.

Referenced by dial_exec_full().

1984 {
1985  struct ast_datastore *cc_datastore;
1986  struct dialed_cc_interfaces *cc_interfaces;
1987  struct ast_cc_monitor *monitor;
1988  struct extension_monitor_pvt *extension_pvt;
1989  struct extension_child_dialstring *child_dialstring;
1990  struct cc_monitor_tree *interface_tree;
1991  int id;
1992 
1993  ast_channel_lock(incoming);
1994  if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) {
1995  ast_channel_unlock(incoming);
1996  return;
1997  }
1998 
1999  cc_interfaces = cc_datastore->data;
2000  interface_tree = cc_interfaces->interface_tree;
2001  id = cc_interfaces->dial_parent_id;
2002  ast_channel_unlock(incoming);
2003 
2004  AST_LIST_LOCK(interface_tree);
2005  AST_LIST_TRAVERSE(interface_tree, monitor, next) {
2006  if (monitor->id == id) {
2007  break;
2008  }
2009  }
2010 
2011  if (!monitor) {
2012  AST_LIST_UNLOCK(interface_tree);
2013  return;
2014  }
2015 
2016  extension_pvt = monitor->private_data;
2017  if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) {
2018  AST_LIST_UNLOCK(interface_tree);
2019  return;
2020  }
2021  ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring));
2022  ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name));
2023  child_dialstring->is_valid = 1;
2024  AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next);
2025  AST_LIST_UNLOCK(interface_tree);
2026 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
unsigned int id
Definition: ccss.h:485
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition: ccss.c:1788
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
char device_name[AST_CHANNEL_NAME]
The name of the device being dialed.
Definition: ccss.c:1773
The "tree" of interfaces that is dialed.
Definition: ccss.c:323
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1907
void * data
Definition: datastore.h:66
char original_dialstring[AST_CHANNEL_NAME]
the original dialstring used to call a particular device
Definition: ccss.c:1754
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Data regarding an extension monitor's child's dialstrings.
Definition: ccss.c:1738
Private data for an extension monitor.
Definition: ccss.c:1795
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:527
unsigned int dial_parent_id
Definition: ccss.c:1880
int ast_cc_failed ( int  core_id,
const char *const  debug,
  ... 
)

Indicate failure has occurred.

Since
1.8

If at any point a failure occurs, this is the function to call so that the core can initiate cleanup procedures.

Parameters
core_idcore_id of the CC transaction
debugoptional string to print for debugging purposes
Return values
0Success
-1Failure

Definition at line 3844 of file ccss.c.

References CC_FAILED.

Referenced by sig_pri_cc_agent_req_rsp().

3845 {
3846  va_list ap;
3847  int res;
3848 
3849  va_start(ap, debug);
3850  res = cc_request_state_change(CC_FAILED, core_id, debug, ap);
3851  va_end(ap);
3852  return res;
3853 }
static int debug
Global debug status.
Definition: res_xmpp.c:441
int ast_cc_get_current_core_id ( struct ast_channel chan)

Get the core id for the current call.

Since
1.8

The main use of this function is for channel drivers who queue an AST_CONTROL_CC frame. A channel driver may call this function in order to get the core_id for what may become a CC request. This way, when monitor functions are called which use a core_id as a means of identification, the channel driver will have saved this information.

The channel given to this function may be an inbound or outbound channel. Both will have the necessary info on it.

Parameters
chanThe channel from which to get the core_id.
Return values
core_idon success
-1Failure

Definition at line 2465 of file ccss.c.

References ast_channel_datastore_find(), dialed_cc_interfaces::core_id, ast_datastore::data, and dialed_cc_interfaces::ignore.

2466 {
2467  struct ast_datastore *datastore;
2468  struct dialed_cc_interfaces *cc_interfaces;
2469  int core_id_return;
2470 
2471  ast_channel_lock(chan);
2472  if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2473  ast_channel_unlock(chan);
2474  return -1;
2475  }
2476 
2477  cc_interfaces = datastore->data;
2478  core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id;
2479  ast_channel_unlock(chan);
2480  return core_id_return;
2481 
2482 }
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
void * data
Definition: datastore.h:66
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.

Since
1.8

The function ast_cc_is_recall is helpful for determining if a call to a specific channel is a recall. However, once you have determined that this is a recall, you will most likely need access to the private data within the associated monitor. This function is what one uses to get that monitor.

Note
This function locks the list of monitors that correspond to the core_id passed in. Be sure that you have no potential lock order issues when calling this function.
Parameters
core_idThe core ID to which this recall corresponds. This likely will have been obtained using the ast_cc_is_recall function
device_nameWhich device to find the monitor for.
Return values
NULLAppropriate monitor does not exist
non-NULLThe monitor to use for this recall

Definition at line 3486 of file ccss.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_cc_monitor::interface, and cc_core_instance::monitors.

Referenced by sig_pri_call().

3487 {
3488  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3489  struct ast_cc_monitor *monitor_iter;
3490 
3491  if (!core_instance) {
3492  return NULL;
3493  }
3494 
3495  AST_LIST_LOCK(core_instance->monitors);
3496  AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
3497  if (!strcmp(monitor_iter->interface->device_name, device_name)) {
3498  /* Found a monitor. */
3499  cc_ref(monitor_iter, "Hand the requester of the monitor a reference");
3500  break;
3501  }
3502  }
3503  AST_LIST_UNLOCK(core_instance->monitors);
3504  cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id");
3505  return monitor_iter;
3506 }
struct cc_monitor_tree * monitors
Definition: ccss.c:344
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
struct ast_cc_interface * interface
Definition: ccss.h:480
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

Note
Useful when reading input as a string, like from dialplan or manager.
Parameters
paramsThe CCSS configuration from which to get the value
nameThe name of the CCSS parameter we want
bufA preallocated buffer to hold the value
buf_lenThe size of buf
Return values
0Success
-1Failure

Definition at line 758 of file ccss.c.

References ast_copy_string(), ast_get_cc_agent_dialstring(), ast_get_cc_agent_policy(), ast_get_cc_callback_sub(), 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(), and ast_get_ccnr_available_timer().

760 {
761  const char *value = NULL;
762 
763  if (!strcasecmp(name, "cc_callback_sub")) {
764  value = ast_get_cc_callback_sub(params);
765  } else if (!strcasecmp(name, "cc_agent_policy")) {
766  value = agent_policy_to_str(ast_get_cc_agent_policy(params));
767  } else if (!strcasecmp(name, "cc_monitor_policy")) {
768  value = monitor_policy_to_str(ast_get_cc_monitor_policy(params));
769  } else if (!strcasecmp(name, "cc_agent_dialstring")) {
770  value = ast_get_cc_agent_dialstring(params);
771  }
772  if (value) {
773  ast_copy_string(buf, value, buf_len);
774  return 0;
775  }
776 
777  /* The rest of these are all ints of some sort and require some
778  * snprintf-itude
779  */
780 
781  if (!strcasecmp(name, "cc_offer_timer")) {
782  snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params));
783  } else if (!strcasecmp(name, "ccnr_available_timer")) {
784  snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params));
785  } else if (!strcasecmp(name, "ccbs_available_timer")) {
786  snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params));
787  } else if (!strcasecmp(name, "cc_max_agents")) {
788  snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params));
789  } else if (!strcasecmp(name, "cc_max_monitors")) {
790  snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params));
791  } else if (!strcasecmp(name, "cc_recall_timer")) {
792  snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params));
793  } else {
794  ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
795  return -1;
796  }
797 
798  return 0;
799 }
unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
Get the ccnr_available_timer.
Definition: ccss.c:908
unsigned int ast_get_cc_recall_timer(struct ast_cc_config_params *config)
Get the cc_recall_timer.
Definition: ccss.c:923
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:876
const char * ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
Get the cc_agent_dialstring.
Definition: ccss.c:953
unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
Get the cc_max_agents.
Definition: ccss.c:967
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition: ccss.c:977
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:859
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
const char * ast_get_cc_callback_sub(struct ast_cc_config_params *config)
Get the name of the callback subroutine.
Definition: ccss.c:987
unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
Get the cc_offer_timer.
Definition: ccss.c:893
unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
Get the ccbs_available_timer.
Definition: ccss.c:938
int ast_cc_is_config_param ( const char *const  name)

Is this a CCSS configuration parameter?

Since
1.8
Parameters
nameName of configuration option being parsed.
Return values
1Yes, this is a CCSS configuration parameter.
0No, this is not a CCSS configuration parameter.

Definition at line 840 of file ccss.c.

841 {
842  return (!strcasecmp(name, "cc_agent_policy") ||
843  !strcasecmp(name, "cc_monitor_policy") ||
844  !strcasecmp(name, "cc_offer_timer") ||
845  !strcasecmp(name, "ccnr_available_timer") ||
846  !strcasecmp(name, "ccbs_available_timer") ||
847  !strcasecmp(name, "cc_max_agents") ||
848  !strcasecmp(name, "cc_max_monitors") ||
849  !strcasecmp(name, "cc_callback_sub") ||
850  !strcasecmp(name, "cc_agent_dialstring") ||
851  !strcasecmp(name, "cc_recall_timer"));
852 }
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.

Since
1.8

When a CC recall happens, it is important on the called side to know that the call is a CC recall and not a normal call. This function will determine first if the call in question is a CC recall. Then it will determine based on the chan parameter if the channel is being called is being recalled.

As a quick example, let's say a call is placed to SIP/1000 and SIP/1000 is currently on the phone. The caller requests CCBS. SIP/1000 finishes his call, and so the caller attempts to recall. Now, the dialplan administrator has set up this second call so that not only is SIP/1000 called, but also SIP/2000 is called. If SIP/1000's channel were passed to this function, the return value would be non-zero, but if SIP/2000's channel were passed into this function, then the return would be 0 since SIP/2000 was not one of the original devices dialed.

Note
This function may be called on a calling channel as well to determine if it is part of a CC recall.
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.
Parameters
chanThe channel to check
[out]core_idIf this is a valid CC recall, the core_id of the failed call will be placed in this output parameter
monitor_typeClarify 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.
Return values
0Either this is not a recall or it is but this channel is not part of the recall
non-zeroThis is a recall and the channel in question is directly involved.

Definition at line 3405 of file ccss.c.

References ast_channel_datastore_find(), ast_channel_get_device_name(), AST_CHANNEL_NAME, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_datastore::data, ast_cc_monitor::interface, and ast_cc_interface::monitor_type.

Referenced by sig_pri_call().

3406 {
3407  struct ast_datastore *recall_datastore;
3408  struct cc_recall_ds_data *recall_data;
3409  struct cc_monitor_tree *interface_tree;
3410  char device_name[AST_CHANNEL_NAME];
3411  struct ast_cc_monitor *device_monitor;
3412  int core_id_candidate;
3413 
3414  ast_assert(core_id != NULL);
3415 
3416  *core_id = -1;
3417 
3418  ast_channel_lock(chan);
3419  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3420  /* Obviously not a recall if the datastore isn't present */
3421  ast_channel_unlock(chan);
3422  return 0;
3423  }
3424 
3425  recall_data = recall_datastore->data;
3426 
3427  if (recall_data->ignore) {
3428  /* Though this is a recall, the call to this particular interface is not part of the
3429  * recall either because this is a call forward or because this is not the first
3430  * invocation of Dial during this call
3431  */
3432  ast_channel_unlock(chan);
3433  return 0;
3434  }
3435 
3436  if (!recall_data->nested) {
3437  /* If the nested flag is not set, then this means that
3438  * the channel passed to this function is the caller making
3439  * the recall. This means that we shouldn't look through
3440  * the monitor tree for the channel because it shouldn't be
3441  * there. However, this is a recall though, so return true.
3442  */
3443  *core_id = recall_data->core_id;
3444  ast_channel_unlock(chan);
3445  return 1;
3446  }
3447 
3448  if (ast_strlen_zero(monitor_type)) {
3449  /* If someone passed a NULL or empty monitor type, then it is clear
3450  * the channel they passed in was an incoming channel, and so searching
3451  * the list of dialed interfaces is not going to be helpful. Just return
3452  * false immediately.
3453  */
3454  ast_channel_unlock(chan);
3455  return 0;
3456  }
3457 
3458  interface_tree = recall_data->interface_tree;
3459  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
3460  /* We grab the value of the recall_data->core_id so that we
3461  * can unlock the channel before we start looking through the
3462  * interface list. That way we don't have to worry about a possible
3463  * clash between the channel lock and the monitor tree lock.
3464  */
3465  core_id_candidate = recall_data->core_id;
3466  ast_channel_unlock(chan);
3467 
3468  /*
3469  * Now we need to find out if the channel device name
3470  * is in the list of interfaces in the called tree.
3471  */
3472  AST_LIST_LOCK(interface_tree);
3473  AST_LIST_TRAVERSE(interface_tree, device_monitor, next) {
3474  if (!strcmp(device_monitor->interface->device_name, device_name) &&
3475  !strcmp(device_monitor->interface->monitor_type, monitor_type)) {
3476  /* BOOM! Device is in the tree! We have a winner! */
3477  *core_id = core_id_candidate;
3478  AST_LIST_UNLOCK(interface_tree);
3479  return 1;
3480  }
3481  }
3482  AST_LIST_UNLOCK(interface_tree);
3483  return 0;
3484 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
int core_id
Definition: ccss.h:494
The "tree" of interfaces that is dialed.
Definition: ccss.c:323
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_CHANNEL_NAME
Definition: channel.h:171
const char * monitor_type
The type of monitor that should be used for this interface.
Definition: ccss.h:793
struct ast_cc_interface * interface
Definition: ccss.h:480
void * data
Definition: datastore.h:66
int ast_channel_get_device_name(struct ast_channel *chan, char *device_name, size_t name_buffer_length)
Get a device name given its channel structure.
Definition: channel.c:10496
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.

Since
1.8
Note
The code in the core will take care of making sure that the information gets passed up the ladder correctly.
core_id The core ID of the corresponding CC transaction
debug
Return values
0Request successfully queued
-1Request could not be queued

Definition at line 3763 of file ccss.c.

References CC_CALLEE_READY.

3764 {
3765  va_list ap;
3766  int res;
3767 
3768  va_start(ap, debug);
3769  res = cc_request_state_change(CC_CALLEE_READY, core_id, debug, ap);
3770  va_end(ap);
3771  return res;
3772 }
static int debug
Global debug status.
Definition: res_xmpp.c:441
int core_id
Definition: ccss.h:494
int ast_cc_monitor_count ( const char *const  name,
const char *const  type 
)

Return the number of outstanding CC requests to a specific device.

Since
1.8
Note
This function will lock the list of monitors stored on every instance of the CC core. Callers of this function should be aware of this and avoid any potential lock ordering problems.
Parameters
nameThe name of the monitored device
typeThe type of the monitored device (e.g. "generic")
Returns
The number of CC requests for the monitor

Definition at line 4333 of file ccss.c.

References ast_log_dynamic_level, cc_logger_level, and OBJ_NODATA.

Referenced by ast_queue_cc_frame().

4334 {
4335  struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,};
4336 
4337  ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents");
4338  ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count);
4339  return data.count;
4340 }
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
static int cc_logger_level
Definition: ccss.c:133
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.

Since
1.8

If a monitor should detect that a failure has occurred when communicating with its endpoint, then ast_cc_monitor_failed should be called. The big difference between ast_cc_monitor_failed and ast_cc_failed is that ast_cc_failed indicates a global failure for a CC transaction, where as ast_cc_monitor_failed is localized to a particular monitor. When ast_cc_failed is called, the entire CC transaction is torn down. When ast_cc_monitor_failed is called, only the monitor on which the failure occurred is pruned from the tree of monitors.

If there are no more devices left to monitor when this function is called, then the core will fail the CC transaction globally.

Parameters
core_idThe core ID for the CC transaction
monitor_nameThe name of the monitor on which the failure occurred
debugA debug message to print to the CC log

Definition at line 3906 of file ccss.c.

References ast_calloc, ast_strdup, ast_taskprocessor_push(), and ast_vasprintf.

Referenced by ast_cc_available_timer_expire().

3907 {
3908  struct ast_cc_monitor_failure_data *failure_data;
3909  int res;
3910  va_list ap;
3911 
3912  if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) {
3913  return -1;
3914  }
3915 
3916  if (!(failure_data->device_name = ast_strdup(monitor_name))) {
3917  ast_free(failure_data);
3918  return -1;
3919  }
3920 
3921  va_start(ap, debug);
3922  if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) {
3923  va_end(ap);
3924  ast_free((char *)failure_data->device_name);
3925  ast_free(failure_data);
3926  return -1;
3927  }
3928  va_end(ap);
3929 
3930  failure_data->core_id = core_id;
3931 
3932  res = ast_taskprocessor_push(cc_core_taskprocessor, cc_monitor_failed, failure_data);
3933  if (res) {
3934  ast_free((char *)failure_data->device_name);
3935  ast_free((char *)failure_data->debug);
3936  ast_free(failure_data);
3937  }
3938  return res;
3939 }
static int debug
Global debug status.
Definition: res_xmpp.c:441
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
Definition: astmm.h:278
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125
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.

Parameters
core_idThe core ID of the CC transaction
Return values
0Successfully alerted the core that party B is free
-1Could not alert the core that party B is free

Definition at line 4016 of file ccss.c.

References ast_taskprocessor_push().

4017 {
4018  int res;
4019  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4020 
4021  if (!core_instance) {
4022  return -1;
4023  }
4024 
4025  res = ast_taskprocessor_push(cc_core_taskprocessor, cc_party_b_free, core_instance);
4026  if (res) {
4027  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4028  }
4029  return res;
4030 }
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125
int ast_cc_monitor_register ( const struct ast_cc_monitor_callbacks callbacks)

Register a set of monitor callbacks with the core.

Since
1.8

This is made so that at monitor creation time, the proper callbacks may be installed and the proper .init callback may be called for the monitor to establish private data.

Parameters
callbacksThe callbacks used by the monitor implementation
Return values
0Successfully registered
-1Failure to register

Definition at line 1162 of file ccss.c.

References ast_calloc, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module().

1163 {
1164  struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend));
1165 
1166  if (!backend) {
1167  return -1;
1168  }
1169 
1170  backend->callbacks = callbacks;
1171 
1173  AST_RWLIST_INSERT_TAIL(&cc_monitor_backends, backend, next);
1175  return 0;
1176 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
int ast_cc_monitor_request_acked ( int  core_id,
const char *const  debug,
  ... 
)

Indicate that an outbound entity has accepted our CC request.

Since
1.8

When we receive confirmation that an outbound device has accepted the CC request we sent it, this function must be called.

Parameters
core_idcore_id of the CC transaction
debugoptional string to print for debugging purposes
Return values
0Success
-1Failure

Definition at line 3752 of file ccss.c.

References CC_ACTIVE.

3753 {
3754  va_list ap;
3755  int res;
3756 
3757  va_start(ap, debug);
3758  res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3759  va_end(ap);
3760  return res;
3761 }
static int debug
Global debug status.
Definition: res_xmpp.c:441
int ast_cc_monitor_status_request ( int  core_id)

Request the status of a caller or callers.

The following are all functions which are required due to the unique case where Asterisk is acting as the NT side of an ISDN PTMP connection to the caller and as the TE side of an ISDN PTMP connection to the callee. In such a case, there are several times where the PTMP monitor needs information from the agent in order to formulate the appropriate messages to send.

When an ISDN PTMP monitor senses that the callee has become available, it needs to know the current status of the caller in order to determine the appropriate response to send to the caller. In order to do this, the monitor calls this function. Responses will arrive asynchronously.

Note
Zero or more responses may come as a result.
Parameters
core_idThe core ID of the CC transaction
Return values
0Successfully requested status
-1Failed to request status

Definition at line 3951 of file ccss.c.

References ast_taskprocessor_push().

3952 {
3953  int res;
3954  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3955 
3956  if (!core_instance) {
3957  return -1;
3958  }
3959 
3960  res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_request, core_instance);
3961  if (res) {
3962  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3963  }
3964  return res;
3965 }
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125
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.

Parameters
core_idThe core ID of the CC transaction
Return values
0Successfully requested for the phone to stop ringing
-1Could not request for the phone to stop ringing

Definition at line 3988 of file ccss.c.

References ast_taskprocessor_push().

3989 {
3990  int res;
3991  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3992 
3993  if (!core_instance) {
3994  return -1;
3995  }
3996 
3997  res = ast_taskprocessor_push(cc_core_taskprocessor, cc_stop_ringing, core_instance);
3998  if (res) {
3999  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4000  }
4001  return res;
4002 }
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125
void ast_cc_monitor_unregister ( const struct ast_cc_monitor_callbacks callbacks)

Unregister a set of monitor callbacks with the core.

Since
1.8

If a module which makes use of a CC monitor is unloaded, then it may unregister its monitor callbacks with the core.

Parameters
callbacksThe callbacks used by the monitor implementation

Definition at line 1195 of file ccss.c.

References AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

1196 {
1197  struct cc_monitor_backend *backend;
1199  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&cc_monitor_backends, backend, next) {
1200  if (backend->callbacks == callbacks) {
1201  AST_RWLIST_REMOVE_CURRENT(next);
1202  ast_free(backend);
1203  break;
1204  }
1205  }
1206  AST_RWLIST_TRAVERSE_SAFE_END;
1208 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
int ast_cc_offer ( struct ast_channel caller_chan)

Offer CC to a caller.

Since
1.8

This function is called from ast_hangup if the caller is eligible to be offered call completion service.

Parameters
caller_chanThe calling channel
Return values
-1Error
0Success

Definition at line 3716 of file ccss.c.

References ast_channel_datastore_find(), dialed_cc_interfaces::core_id, ast_datastore::data, and dialed_cc_interfaces::is_original_caller.

Referenced by ast_hangup().

3717 {
3718  int core_id;
3719  int res = -1;
3720  struct ast_datastore *datastore;
3721  struct dialed_cc_interfaces *cc_interfaces;
3722  char cc_is_offerable;
3723 
3724  ast_channel_lock(caller_chan);
3725  if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) {
3726  ast_channel_unlock(caller_chan);
3727  return res;
3728  }
3729 
3730  cc_interfaces = datastore->data;
3731  cc_is_offerable = cc_interfaces->is_original_caller;
3732  core_id = cc_interfaces->core_id;
3733  ast_channel_unlock(caller_chan);
3734 
3735  if (cc_is_offerable) {
3736  res = cc_offer(core_id, "CC offered to caller %s", ast_channel_name(caller_chan));
3737  }
3738  return res;
3739 }
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
char is_original_caller
Definition: ccss.c:1903
void * data
Definition: datastore.h:66
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.

Since
1.8

It is recommended that an entity which receives an incoming CC request calls this function before calling ast_cc_agent_accept_request. This way, immediate feedback can be given to the caller about why his request was rejected.

If this is not called and a state change to CC_CALLER_REQUESTED is made, then the core will still not allow for the request to succeed. However, if done this way, it may not be obvious to the requestor why the request failed.

Return values
0Not within the limits. Fail.
non-zeroWithin the limits. Success.

Definition at line 2460 of file ccss.c.

References cc_request_count, and global_cc_max_requests.

2461 {
2463 }
static unsigned int global_cc_max_requests
Definition: ccss.c:137
static int cc_request_count
Definition: ccss.c:141
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

Note
Useful when parsing config files when used in conjunction with ast_ccss_is_cc_config_param.
Parameters
paramsThe parameter structure to set the value on
nameThe name of the cc parameter
valueThe value of the parameter
Return values
0Success
-1Failure

Definition at line 801 of file ccss.c.

References ast_set_cc_agent_dialstring(), ast_set_cc_agent_policy(), ast_set_cc_callback_sub(), 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(), and ast_set_ccnr_available_timer().

803 {
804  unsigned int value_as_uint;
805  if (!strcasecmp(name, "cc_agent_policy")) {
806  return ast_set_cc_agent_policy(params, str_to_agent_policy(value));
807  } else if (!strcasecmp(name, "cc_monitor_policy")) {
808  return ast_set_cc_monitor_policy(params, str_to_monitor_policy(value));
809  } else if (!strcasecmp(name, "cc_agent_dialstring")) {
810  ast_set_cc_agent_dialstring(params, value);
811  } else if (!strcasecmp(name, "cc_callback_sub")) {
812  ast_set_cc_callback_sub(params, value);
813  return 0;
814  }
815 
816  if (sscanf(value, "%30u", &value_as_uint) != 1) {
817  return -1;
818  }
819 
820  if (!strcasecmp(name, "cc_offer_timer")) {
821  ast_set_cc_offer_timer(params, value_as_uint);
822  } else if (!strcasecmp(name, "ccnr_available_timer")) {
823  ast_set_ccnr_available_timer(params, value_as_uint);
824  } else if (!strcasecmp(name, "ccbs_available_timer")) {
825  ast_set_ccbs_available_timer(params, value_as_uint);
826  } else if (!strcasecmp(name, "cc_max_agents")) {
827  ast_set_cc_max_agents(params, value_as_uint);
828  } else if (!strcasecmp(name, "cc_max_monitors")) {
829  ast_set_cc_max_monitors(params, value_as_uint);
830  } else if (!strcasecmp(name, "cc_recall_timer")) {
831  ast_set_cc_recall_timer(params, value_as_uint);
832  } else {
833  ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
834  return -1;
835  }
836 
837  return 0;
838 }
void ast_set_cc_callback_sub(struct ast_cc_config_params *config, const char *const value)
Set the callback subroutine name.
Definition: ccss.c:992
void ast_set_cc_agent_dialstring(struct ast_cc_config_params *config, const char *const value)
Set the cc_agent_dialstring.
Definition: ccss.c:958
void ast_set_ccbs_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccbs_available_timer.
Definition: ccss.c:943
int ast_set_cc_monitor_policy(struct ast_cc_config_params *config, enum ast_cc_monitor_policies value)
Set the cc_monitor_policy.
Definition: ccss.c:881
void ast_set_cc_max_monitors(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_monitors.
Definition: ccss.c:982
void ast_set_cc_offer_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_offer_timer.
Definition: ccss.c:898
void ast_set_ccnr_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccnr_available_timer.
Definition: ccss.c:913
void ast_set_cc_recall_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_recall_timer.
Definition: ccss.c:928
void ast_set_cc_max_agents(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_agents.
Definition: ccss.c:972
int ast_set_cc_agent_policy(struct ast_cc_config_params *config, enum ast_cc_agent_policies value)
Set the cc_agent_policy.
Definition: ccss.c:864
const char* ast_get_cc_agent_dialstring ( struct ast_cc_config_params config)

Get the cc_agent_dialstring.

Since
1.8
Parameters
configThe configuration to retrieve the cc_agent_dialstring from
Returns
The cc_agent_dialstring from this configuration

Definition at line 953 of file ccss.c.

Referenced by ast_cc_get_param().

954 {
955  return config->cc_agent_dialstring;
956 }
enum ast_cc_agent_policies ast_get_cc_agent_policy ( struct ast_cc_config_params config)

Get the cc_agent_policy.

Since
1.8
Parameters
configThe configuration to retrieve the policy from
Returns
The current cc_agent_policy for this configuration

Definition at line 859 of file ccss.c.

Referenced by ast_cc_call_init(), and ast_cc_get_param().

860 {
861  return config->cc_agent_policy;
862 }
const char* ast_get_cc_callback_sub ( struct ast_cc_config_params config)

Get the name of the callback subroutine.

Since
11
Parameters
configThe configuration to retrieve the callback_sub from
Returns
The callback_sub name

Definition at line 987 of file ccss.c.

Referenced by ast_cc_get_param().

988 {
989  return config->cc_callback_sub;
990 }
unsigned int ast_get_cc_max_agents ( struct ast_cc_config_params config)

Get the cc_max_agents.

Since
1.8
Parameters
configThe configuration to retrieve the cc_max_agents from
Returns
The cc_max_agents from this configuration

Definition at line 967 of file ccss.c.

Referenced by ast_cc_get_param().

968 {
969  return config->cc_max_agents;
970 }
unsigned int ast_get_cc_max_monitors ( struct ast_cc_config_params config)

Get the cc_max_monitors.

Since
1.8
Parameters
configThe configuration to retrieve the cc_max_monitors from
Returns
The cc_max_monitors from this configuration

Definition at line 977 of file ccss.c.

Referenced by ast_cc_get_param(), and ast_queue_cc_frame().

978 {
979  return config->cc_max_monitors;
980 }
enum ast_cc_monitor_policies ast_get_cc_monitor_policy ( struct ast_cc_config_params config)

Get the cc_monitor_policy.

Since
1.8
Parameters
configThe configuration to retrieve the cc_monitor_policy from
Returns
The cc_monitor_policy retrieved from the configuration

Definition at line 876 of file ccss.c.

Referenced by ast_cc_call_failed(), ast_cc_get_param(), and dahdi_cc_callback().

877 {
878  return config->cc_monitor_policy;
879 }
unsigned int ast_get_cc_offer_timer ( struct ast_cc_config_params config)

Get the cc_offer_timer.

Since
1.8
Parameters
configThe configuration to retrieve the cc_offer_timer from
Returns
The cc_offer_timer from this configuration

Definition at line 893 of file ccss.c.

Referenced by ast_cc_get_param().

894 {
895  return config->cc_offer_timer;
896 }
unsigned int ast_get_cc_recall_timer ( struct ast_cc_config_params config)

Get the cc_recall_timer.

Since
1.8
Parameters
configThe configuration to retrieve the cc_recall_timer from
Returns
The cc_recall_timer from this configuration

Definition at line 923 of file ccss.c.

Referenced by ast_cc_get_param().

924 {
925  return config->cc_recall_timer;
926 }
unsigned int ast_get_ccbs_available_timer ( struct ast_cc_config_params config)

Get the ccbs_available_timer.

Since
1.8
Parameters
configThe configuration to retrieve the ccbs_available_timer from
Returns
The ccbs_available_timer from this configuration

Definition at line 938 of file ccss.c.

Referenced by ast_cc_get_param().

939 {
940  return config->ccbs_available_timer;
941 }
unsigned int ast_get_ccnr_available_timer ( struct ast_cc_config_params config)

Get the ccnr_available_timer.

Since
1.8
Parameters
configThe configuration to retrieve the ccnr_available_timer from
Returns
The ccnr_available_timer from this configuration

Definition at line 908 of file ccss.c.

Referenced by ast_cc_get_param().

909 {
910  return config->ccnr_available_timer;
911 }
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 2293 of file ccss.c.

References ast_channel_datastore_find(), AST_CONTROL_CC, ast_indicate_data(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log_dynamic_level, cc_logger_level, cc_core_instance::core_id, dialed_cc_interfaces::core_id, ast_datastore::data, cc_control_payload::device_name, extension_child_dialstring::device_name, cc_control_payload::dialstring, ast_cc_monitor::dialstring, dialed_cc_interfaces::ignore, ast_cc_monitor::interface, dialed_cc_interfaces::interface_tree, dialed_cc_interfaces::is_original_caller, cc_control_payload::monitor_type, ast_cc_monitor::parent_id, cc_control_payload::private_data, and cc_control_payload::service.

Referenced by ast_cc_busy_interface(), and ast_cc_call_failed().

2294 {
2295  char *device_name;
2296  char *dialstring;
2297  struct ast_cc_monitor *monitor;
2298  struct ast_datastore *cc_datastore;
2299  struct dialed_cc_interfaces *cc_interfaces;
2300  struct cc_control_payload *cc_data = frame_data;
2301  struct cc_core_instance *core_instance;
2302 
2303  device_name = cc_data->device_name;
2304  dialstring = cc_data->dialstring;
2305 
2306  ast_channel_lock(inbound);
2307  if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
2308  ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name);
2309  ast_channel_unlock(inbound);
2310  call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
2311  return;
2312  }
2313 
2314  cc_interfaces = cc_datastore->data;
2315 
2316  if (cc_interfaces->ignore) {
2317  ast_channel_unlock(inbound);
2318  call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
2319  return;
2320  }
2321 
2322  if (!cc_interfaces->is_original_caller) {
2323  /* If the is_original_caller is not set on the *inbound* channel, then
2324  * it must be a local channel. As such, we do not want to create a core instance
2325  * or an agent for the local channel. Instead, we want to pass this along to the
2326  * other side of the local channel so that the original caller can benefit.
2327  */
2328  ast_channel_unlock(inbound);
2329  ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data));
2330  return;
2331  }
2332 
2333  core_instance = find_cc_core_instance(cc_interfaces->core_id);
2334  if (!core_instance) {
2335  core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree,
2336  cc_interfaces->core_id, cc_data);
2337  if (!core_instance) {
2338  cc_interfaces->ignore = 1;
2339  ast_channel_unlock(inbound);
2340  call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
2341  return;
2342  }
2343  }
2344 
2345  ast_channel_unlock(inbound);
2346 
2347  /* Yeah this kind of sucks, but luckily most people
2348  * aren't dialing thousands of interfaces on every call
2349  *
2350  * This traversal helps us to not create duplicate monitors in
2351  * case a device queues multiple CC control frames.
2352  */
2353  AST_LIST_LOCK(cc_interfaces->interface_tree);
2354  AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) {
2355  if (!strcmp(monitor->interface->device_name, device_name)) {
2356  ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n",
2357  core_instance->core_id, device_name);
2358  AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2359  cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2360  call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
2361  return;
2362  }
2363  }
2364  AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2365 
2366  if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) {
2367  ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name);
2368  cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2369  call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
2370  return;
2371  }
2372 
2373  AST_LIST_LOCK(cc_interfaces->interface_tree);
2374  cc_ref(monitor, "monitor tree's reference to the monitor");
2375  AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next);
2376  AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2377 
2378  cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0);
2379 
2380  cc_publish_available(cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service));
2381 
2382  cc_unref(core_instance, "Done with core_instance after handling CC control frame");
2383  cc_unref(monitor, "Unref reference from allocating monitor");
2384 }
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:221
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
void * private_data
Private data allocated by the callee.
Definition: ccss.c:256
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4653
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
unsigned int parent_id
Definition: ccss.h:490
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:292
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:304
char is_original_caller
Definition: ccss.c:1903
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
enum ast_cc_service_type service
Service offered by the endpoint.
Definition: ccss.c:265
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
struct ast_cc_interface * interface
Definition: ccss.h:480
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1907
void * data
Definition: datastore.h:66
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:239
static int cc_logger_level
Definition: ccss.c:133
void ast_ignore_cc ( struct ast_channel chan)

Mark the channel to ignore further CC activity.

Since
1.8

When a CC-capable application, such as Dial, has finished with all CC processing for a channel and knows that any further CC processing should be ignored, this function should be called.

Parameters
chanThe channel for which further CC processing should be ignored.

Definition at line 3685 of file ccss.c.

References ast_channel_datastore_find(), ast_datastore::data, and dialed_cc_interfaces::ignore.

Referenced by dial_exec_full(), and do_forward().

3686 {
3687  struct ast_datastore *cc_datastore;
3688  struct ast_datastore *cc_recall_datastore;
3689  struct dialed_cc_interfaces *cc_interfaces;
3690  struct cc_recall_ds_data *recall_cc_data;
3691 
3692  ast_channel_lock(chan);
3693  if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
3694  cc_interfaces = cc_datastore->data;
3695  cc_interfaces->ignore = 1;
3696  }
3697 
3698  if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3699  recall_cc_data = cc_recall_datastore->data;
3700  recall_cc_data->ignore = 1;
3701  }
3702  ast_channel_unlock(chan);
3703 }
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
void * data
Definition: datastore.h:66
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.

Since
1.8
Note
Since this function calls ast_queue_frame, the channel will be locked during the course of this function.
Parameters
chanThe channel onto which to queue the frame
monitor_typeThe type of monitor to use when CC is requested
dialstringThe dial string used to call the device
serviceThe type of CC service the device is willing to offer
private_dataIf 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.
Return values
0Success
-1Error

Definition at line 4114 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_get_cc_max_monitors(), and ast_queue_frame().

4116 {
4117  struct ast_frame frame = {0,};
4118  char device_name[AST_CHANNEL_NAME];
4119  int retval;
4120  struct ast_cc_config_params *cc_params;
4121 
4122  cc_params = ast_channel_get_cc_config_params(chan);
4123  if (!cc_params) {
4124  return -1;
4125  }
4126  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4127  if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
4128  ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
4129  return -1;
4130  }
4131 
4132  if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) {
4133  /* Frame building failed. We can't use this. */
4134  return -1;
4135  }
4136  retval = ast_queue_frame(chan, &frame);
4137  ast_frfree(&frame);
4138  return retval;
4139 }
struct ast_cc_config_params * ast_channel_get_cc_config_params(struct ast_channel *chan)
Get the CCSS parameters from a channel.
Definition: channel.c:10474
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139
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.
Definition: ccss.c:4141
#define AST_CHANNEL_NAME
Definition: channel.h:171
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition: ccss.c:977
int ast_channel_get_device_name(struct ast_channel *chan, char *device_name, size_t name_buffer_length)
Get a device name given its channel structure.
Definition: channel.c:10496
Data structure associated with a single frame of data.
int ast_cc_monitor_count(const char *const name, const char *const type)
Return the number of outstanding CC requests to a specific device.
Definition: ccss.c:4333
void ast_set_cc_agent_dialstring ( struct ast_cc_config_params config,
const char *const  value 
)

Set the cc_agent_dialstring.

Since
1.8
Parameters
configThe configuration to set the cc_agent_dialstring on
valueThe new cc_agent_dialstring we want to change to

Definition at line 958 of file ccss.c.

References ast_copy_string().

Referenced by ast_cc_set_param().

959 {
960  if (ast_strlen_zero(value)) {
961  config->cc_agent_dialstring[0] = '\0';
962  } else {
963  ast_copy_string(config->cc_agent_dialstring, value, sizeof(config->cc_agent_dialstring));
964  }
965 }
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
int ast_set_cc_agent_policy ( struct ast_cc_config_params config,
enum ast_cc_agent_policies  value 
)

Set the cc_agent_policy.

Since
1.8
Parameters
configThe configuration to set the cc_agent_policy on
valueThe new cc_agent_policy we want to change to
Return values
0Success
-1Failure (likely due to bad input)

Definition at line 864 of file ccss.c.

References AST_CC_AGENT_GENERIC.

Referenced by ast_cc_set_param().

865 {
866  /* Screw C and its weak type checking for making me have to do this
867  * validation at runtime.
868  */
869  if (value < AST_CC_AGENT_NEVER || value > AST_CC_AGENT_GENERIC) {
870  return -1;
871  }
872  config->cc_agent_policy = value;
873  return 0;
874 }
void ast_set_cc_callback_sub ( struct ast_cc_config_params config,
const char *const  value 
)

Set the callback subroutine name.

Since
11
Parameters
configThe configuration to set the callback_sub on
valueThe new callback subroutine we want to change to

Definition at line 992 of file ccss.c.

References ast_copy_string().

Referenced by ast_cc_set_param().

993 {
994  if (ast_strlen_zero(value)) {
995  config->cc_callback_sub[0] = '\0';
996  } else {
997  ast_copy_string(config->cc_callback_sub, value, sizeof(config->cc_callback_sub));
998  }
999 }
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
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.

Since
1.8
extension@context 
as a starting point

The CC_INTERFACES channel variable will have the interfaces that should be called back for a specific PBX instance. This version of the function is used mainly by local channels, wherein we need to set CC_INTERFACES based on an extension and context that appear in the middle of the tree of dialed interfaces.

Note
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.
Parameters
chanThe channel to set the CC_INTERFACES variable on
extensionThe name of the extension for which we're setting the variable. This should be in the form of
exten@context 

Definition at line 3633 of file ccss.c.

References ast_channel_datastore_find(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_str_buffer(), ast_str_create, cc_logger_level, ast_datastore::data, ast_cc_monitor::interface, and pbx_builtin_setvar_helper().

Referenced by local_call().

3634 {
3635  struct ast_datastore *recall_datastore;
3636  struct cc_monitor_tree *interface_tree;
3637  struct ast_cc_monitor *monitor_iter;
3638  struct cc_recall_ds_data *recall_data;
3639  struct ast_str *str = ast_str_create(64);
3640  int core_id;
3641 
3642  if (!str) {
3643  return -1;
3644  }
3645 
3646  ast_channel_lock(chan);
3647  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3648  ast_channel_unlock(chan);
3649  ast_free(str);
3650  return -1;
3651  }
3652  recall_data = recall_datastore->data;
3653  interface_tree = recall_data->interface_tree;
3654  core_id = recall_data->core_id;
3655  ast_channel_unlock(chan);
3656 
3657  AST_LIST_LOCK(interface_tree);
3658  AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) {
3659  if (!strcmp(monitor_iter->interface->device_name, extension)) {
3660  break;
3661  }
3662  }
3663 
3664  if (!monitor_iter) {
3665  /* We couldn't find this extension. This may be because
3666  * we have been directed into an unexpected extension because
3667  * the admin has changed a CC_INTERFACES variable at some point.
3668  */
3669  AST_LIST_UNLOCK(interface_tree);
3670  ast_free(str);
3671  return -1;
3672  }
3673 
3674  build_cc_interfaces_chanvar(monitor_iter, &str);
3675  AST_LIST_UNLOCK(interface_tree);
3676 
3677  pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3678  ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3679  core_id, ast_str_buffer(str));
3680 
3681  ast_free(str);
3682  return 0;
3683 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
structure to hold extensions
Support for dynamic strings.
Definition: strings.h:623
The "tree" of interfaces that is dialed.
Definition: ccss.c:323
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
struct ast_cc_interface * interface
Definition: ccss.h:480
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void * data
Definition: datastore.h:66
static int cc_logger_level
Definition: ccss.c:133
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
void ast_set_cc_max_agents ( struct ast_cc_config_params config,
unsigned int  value 
)

Set the cc_max_agents.

Since
1.8
Parameters
configThe configuration to set the cc_max_agents on
valueThe new cc_max_agents we want to change to

Definition at line 972 of file ccss.c.

Referenced by ast_cc_set_param().

973 {
974  config->cc_max_agents = value;
975 }
void ast_set_cc_max_monitors ( struct ast_cc_config_params config,
unsigned int  value 
)

Set the cc_max_monitors.

Since
1.8
Parameters
configThe configuration to set the cc_max_monitors on
valueThe new cc_max_monitors we want to change to

Definition at line 982 of file ccss.c.

Referenced by ast_cc_set_param().

983 {
984  config->cc_max_monitors = value;
985 }
int ast_set_cc_monitor_policy ( struct ast_cc_config_params config,
enum ast_cc_monitor_policies  value 
)

Set the cc_monitor_policy.

Since
1.8
Parameters
configThe configuration to set the cc_monitor_policy on
valueThe new cc_monitor_policy we want to change to
Return values
0Success
-1Failure (likely due to bad input)

Definition at line 881 of file ccss.c.

References AST_CC_MONITOR_ALWAYS.

Referenced by ast_cc_set_param().

882 {
883  /* Screw C and its weak type checking for making me have to do this
884  * validation at runtime.
885  */
886  if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) {
887  return -1;
888  }
889  config->cc_monitor_policy = value;
890  return 0;
891 }
void ast_set_cc_offer_timer ( struct ast_cc_config_params config,
unsigned int  value 
)

Set the cc_offer_timer.

Since
1.8
Parameters
configThe configuration to set the cc_offer_timer on
valueThe new cc_offer_timer we want to change to

Definition at line 898 of file ccss.c.

Referenced by ast_cc_set_param().

899 {
900  /* 0 is an unreasonable value for any timer. Stick with the default */
901  if (value == 0) {
902  ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer);
903  return;
904  }
905  config->cc_offer_timer = value;
906 }
void ast_set_cc_recall_timer ( struct ast_cc_config_params config,
unsigned int  value 
)

Set the cc_recall_timer.

Since
1.8
Parameters
configThe configuration to set the cc_recall_timer on
valueThe new cc_recall_timer we want to change to

Definition at line 928 of file ccss.c.

Referenced by ast_cc_set_param().

929 {
930  /* 0 is an unreasonable value for any timer. Stick with the default */
931  if (value == 0) {
932  ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->cc_recall_timer);
933  return;
934  }
935  config->cc_recall_timer = value;
936 }
void ast_set_ccbs_available_timer ( struct ast_cc_config_params config,
unsigned int  value 
)

Set the ccbs_available_timer.

Since
1.8
Parameters
configThe configuration to set the ccbs_available_timer on
valueThe new ccbs_available_timer we want to change to

Definition at line 943 of file ccss.c.

Referenced by ast_cc_set_param().

944 {
945  /* 0 is an unreasonable value for any timer. Stick with the default */
946  if (value == 0) {
947  ast_log(LOG_WARNING, "0 is an invalid value for ccbs_available_timer. Retaining value as %u\n", config->ccbs_available_timer);
948  return;
949  }
950  config->ccbs_available_timer = value;
951 }
void ast_set_ccnr_available_timer ( struct ast_cc_config_params config,
unsigned int  value 
)

Set the ccnr_available_timer.

Since
1.8
Parameters
configThe configuration to set the ccnr_available_timer on
valueThe new ccnr_available_timer we want to change to

Definition at line 913 of file ccss.c.

Referenced by ast_cc_set_param().

914 {
915  /* 0 is an unreasonable value for any timer. Stick with the default */
916  if (value == 0) {
917  ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->ccnr_available_timer);
918  return;
919  }
920  config->ccnr_available_timer = value;
921 }
int ast_setup_cc_recall_datastore ( struct ast_channel chan,
const int  core_id 
)

Set up a CC recall datastore on a channel.

Since
1.8

Implementers of protocol-specific CC agents will need to call this function in order for the channel to have the necessary interfaces to recall.

This function must be called by the implementer once it has been detected that an inbound call is a cc_recall. After allocating the channel, call this function, followed by ast_cc_set_cc_interfaces_chanvar. While it would be nice to be able to have the core do this automatically, it just cannot be done given the current architecture.

Definition at line 3372 of file ccss.c.

References ast_calloc, ast_channel_datastore_add(), ast_datastore_free(), cc_core_instance::core_id, ast_datastore::data, ast_datastore::inheritance, and cc_core_instance::monitors.

3373 {
3374  struct ast_datastore *recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL);
3375  struct cc_recall_ds_data *recall_data;
3376  struct cc_core_instance *core_instance;
3377 
3378  if (!recall_datastore) {
3379  return -1;
3380  }
3381 
3382  if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) {
3383  ast_datastore_free(recall_datastore);
3384  return -1;
3385  }
3386 
3387  if (!(core_instance = find_cc_core_instance(core_id))) {
3388  ast_free(recall_data);
3389  ast_datastore_free(recall_datastore);
3390  return -1;
3391  }
3392 
3393  recall_data->interface_tree = cc_ref(core_instance->monitors,
3394  "Bump refcount for monitor tree for recall datastore");
3395  recall_data->core_id = core_id;
3396  recall_datastore->data = recall_data;
3397  recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
3398  ast_channel_lock(chan);
3399  ast_channel_datastore_add(chan, recall_datastore);
3400  ast_channel_unlock(chan);
3401  cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref");
3402  return 0;
3403 }
struct cc_monitor_tree * monitors
Definition: ccss.c:344
Structure for a data store object.
Definition: datastore.h:64
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
unsigned int inheritance
Definition: datastore.h:69
void * data
Definition: datastore.h:66
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
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.

Parameters
core_instanceThe core instance we are checking for the existence of device monitors
Return values
0No device monitors exist on this core_instance
1There is still at least 1 device monitor remaining

Definition at line 3060 of file ccss.c.

References AST_LIST_TRAVERSE, ast_cc_monitor::interface, and cc_core_instance::monitors.

3061 {
3062  struct ast_cc_monitor *iter;
3063  int res = 0;
3064 
3065  AST_LIST_TRAVERSE(core_instance->monitors, iter, next) {
3066  if (iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3067  res = 1;
3068  break;
3069  }
3070  }
3071 
3072  return res;
3073 }
struct cc_monitor_tree * monitors
Definition: ccss.c:344
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
struct ast_cc_interface * interface
Definition: ccss.h:480

Variable Documentation

struct ast_cli_entry cc_cli[]
static
Initial value:
= {
{ .handler = handle_cc_status , .summary = "Reports CC stats" ,},
{ .handler = handle_cc_kill , .summary = "Kill a CC transaction" ,},
}

Definition at line 4583 of file ccss.c.

struct ast_taskprocessor* cc_core_taskprocessor
static

Taskprocessor from which all CC agent and monitor callbacks are called.

Definition at line 125 of file ccss.c.

int cc_logger_level
static

Logger level registered by the CC core.

Definition at line 133 of file ccss.c.

Referenced by ast_cc_agent_set_interfaces_chanvar(), ast_cc_call_init(), ast_cc_monitor_count(), ast_handle_cc_control_frame(), and ast_set_cc_interfaces_chanvar().

const char* CC_LOGGER_LEVEL_NAME = "CC"
static

Name printed on all CC log messages.

Definition at line 129 of file ccss.c.

int cc_request_count
static

The current number of CC requests in the system

Definition at line 141 of file ccss.c.

Referenced by ast_cc_request_is_within_limits().

struct ast_sched_context* cc_sched_context
static

The ast_sched_context used for all generic CC timeouts

Definition at line 115 of file ccss.c.

int core_id_counter
static

Counter used to create core IDs for CC calls. Each new core ID is created by atomically adding 1 to the core_id_counter

Definition at line 120 of file ccss.c.

int dialed_cc_interface_counter
static

This counter is used for assigning unique ids to CC-enabled dialed interfaces.

Definition at line 1853 of file ccss.c.

const 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 1967 of file ccss.c.

unsigned int global_cc_max_requests
static

Parsed configuration value for cc_max_requests

Definition at line 137 of file ccss.c.

Referenced by ast_cc_request_is_within_limits().

const 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 3366 of file ccss.c.