Asterisk - The Open Source Telephony Project GIT-master-9647a4f
Loading...
Searching...
No Matches
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"
Include dependency graph for ccss.c:

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
 
#define RETURN_IF_NOT_ENABLED(rc)
 

Enumerations

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

Functions

struct ast_cc_config_params__ast_cc_config_params_init (const char *file, int line, const char *function)
 Allocate and initialize an ast_cc_config_params structure.
 
static void __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.
 
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.
 
int ast_cc_agent_caller_available (int core_id, const char *const debug,...)
 Indicate that a previously unavailable caller has become available.
 
int ast_cc_agent_caller_busy (int core_id, const char *debug,...)
 Indicate that the caller is busy.
 
int ast_cc_agent_recalling (int core_id, const char *const debug,...)
 Tell the CC core that a caller is currently recalling.
 
int ast_cc_agent_register (const struct ast_cc_agent_callbacks *callbacks)
 Register a set of agent callbacks with the core.
 
int ast_cc_agent_set_interfaces_chanvar (struct ast_channel *chan)
 Set the first level CC_INTERFACES channel variable for a channel.
 
int ast_cc_agent_status_response (int core_id, enum ast_device_state devstate)
 Response with a caller's current status.
 
void ast_cc_agent_unregister (const struct ast_cc_agent_callbacks *callbacks)
 Unregister a set of agent callbacks with the core.
 
int ast_cc_available_timer_expire (const void *data)
 Scheduler callback for available timer expiration.
 
int ast_cc_build_frame (struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, enum ast_cc_service_type service, void *private_data, struct ast_frame *frame)
 Create a CC Control frame.
 
void ast_cc_busy_interface (struct ast_channel *inbound, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, void *private_data)
 Callback made from ast_cc_callback for certain channel types.
 
void ast_cc_call_failed (struct ast_channel *incoming, struct ast_channel *outgoing, const char *const dialstring)
 Make CCBS available in the case that ast_call fails.
 
int ast_cc_call_init (struct ast_channel *chan, int *ignore_cc)
 Start the CC process on a call.
 
int ast_cc_callback (struct ast_channel *inbound, const char *const tech, const char *const dest, ast_cc_callback_fn callback)
 Run a callback for potential matching destinations.
 
int ast_cc_completed (struct ast_channel *chan, const char *const debug,...)
 Indicate recall has been acknowledged.
 
void ast_cc_config_params_destroy (struct ast_cc_config_params *params)
 Free memory from CCSS configuration params.
 
void ast_cc_copy_config_params (struct ast_cc_config_params *dest, const struct ast_cc_config_params *src)
 copy CCSS configuration parameters from one structure to another
 
void ast_cc_default_config_params (struct ast_cc_config_params *params)
 Set the specified CC config params to default values.
 
void ast_cc_extension_monitor_add_dialstring (struct ast_channel *incoming, const char *const dialstring, const char *const device_name)
 Add a child dialstring to an extension monitor.
 
int ast_cc_failed (int core_id, const char *const debug,...)
 Indicate failure has occurred.
 
int ast_cc_get_current_core_id (struct ast_channel *chan)
 Get the core id for the current call.
 
struct ast_cc_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.
 
int ast_cc_get_param (struct ast_cc_config_params *params, const char *const name, char *buf, size_t buf_len)
 get a CCSS configuration parameter, given its name
 
int ast_cc_is_config_param (const char *const name)
 Is this a CCSS configuration parameter?
 
int ast_cc_is_enabled (void)
 Determine if CCSS is enabled.
 
int ast_cc_is_recall (struct ast_channel *chan, int *core_id, const char *const monitor_type)
 Decide if a call to a particular channel is a CC recall.
 
int ast_cc_monitor_callee_available (const int core_id, const char *const debug,...)
 Alert the core that a device being monitored has become available.
 
int ast_cc_monitor_count (const char *const name, const char *const type)
 Return the number of outstanding CC requests to a specific device.
 
int ast_cc_monitor_failed (int core_id, const char *const monitor_name, const char *const debug,...)
 Indicate that a failure has occurred on a specific monitor.
 
int ast_cc_monitor_party_b_free (int core_id)
 Alert a caller that though the callee has become free, the caller himself is not and may not call back.
 
int ast_cc_monitor_register (const struct ast_cc_monitor_callbacks *callbacks)
 Register a set of monitor callbacks with the core.
 
int ast_cc_monitor_request_acked (int core_id, const char *const debug,...)
 Indicate that an outbound entity has accepted our CC request.
 
int ast_cc_monitor_status_request (int core_id)
 Request the status of a caller or callers.
 
int ast_cc_monitor_stop_ringing (int core_id)
 Alert a caller to stop ringing.
 
void ast_cc_monitor_unregister (const struct ast_cc_monitor_callbacks *callbacks)
 Unregister a set of monitor callbacks with the core.
 
int ast_cc_offer (struct ast_channel *caller_chan)
 Offer CC to a caller.
 
int ast_cc_request_is_within_limits (void)
 Check if the incoming CC request is within the bounds set by the cc_max_requests configuration option.
 
int ast_cc_set_param (struct ast_cc_config_params *params, const char *const name, const char *const value)
 set a CCSS configuration parameter, given its name
 
const char * ast_get_cc_agent_dialstring (struct ast_cc_config_params *config)
 Get the cc_agent_dialstring.
 
enum ast_cc_agent_policies ast_get_cc_agent_policy (struct ast_cc_config_params *config)
 Get the cc_agent_policy.
 
const char * ast_get_cc_callback_sub (struct ast_cc_config_params *config)
 Get the name of the callback subroutine.
 
unsigned int ast_get_cc_max_agents (struct ast_cc_config_params *config)
 Get the cc_max_agents.
 
unsigned int ast_get_cc_max_monitors (struct ast_cc_config_params *config)
 Get the cc_max_monitors.
 
enum ast_cc_monitor_policies ast_get_cc_monitor_policy (struct ast_cc_config_params *config)
 Get the cc_monitor_policy.
 
unsigned int ast_get_cc_offer_timer (struct ast_cc_config_params *config)
 Get the cc_offer_timer.
 
unsigned int ast_get_cc_recall_timer (struct ast_cc_config_params *config)
 Get the cc_recall_timer.
 
unsigned int ast_get_ccbs_available_timer (struct ast_cc_config_params *config)
 Get the ccbs_available_timer.
 
unsigned int ast_get_ccnr_available_timer (struct ast_cc_config_params *config)
 Get the ccnr_available_timer.
 
void ast_handle_cc_control_frame (struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
 Properly react to a CC control frame.
 
void ast_ignore_cc (struct ast_channel *chan)
 Mark the channel to ignore further CC activity.
 
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.
 
void ast_set_cc_agent_dialstring (struct ast_cc_config_params *config, const char *const value)
 Set the cc_agent_dialstring.
 
int ast_set_cc_agent_policy (struct ast_cc_config_params *config, enum ast_cc_agent_policies value)
 Set the cc_agent_policy.
 
void ast_set_cc_callback_sub (struct ast_cc_config_params *config, const char *const value)
 Set the callback subroutine name.
 
int ast_set_cc_interfaces_chanvar (struct ast_channel *chan, const char *const extension)
 Set the CC_INTERFACES channel variable for a channel using an.
 
void ast_set_cc_max_agents (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_max_agents.
 
void ast_set_cc_max_monitors (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_max_monitors.
 
int ast_set_cc_monitor_policy (struct ast_cc_config_params *config, enum ast_cc_monitor_policies value)
 Set the cc_monitor_policy.
 
void ast_set_cc_offer_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_offer_timer.
 
void ast_set_cc_recall_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_recall_timer.
 
void ast_set_ccbs_available_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the ccbs_available_timer.
 
void ast_set_ccnr_available_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the ccnr_available_timer.
 
int ast_setup_cc_recall_datastore (struct ast_channel *chan, const int core_id)
 Set up a CC recall datastore on a channel.
 
static void build_cc_interfaces_chanvar (struct ast_cc_monitor *starting_point, struct ast_str **str)
 
static void call_destructor_with_no_monitor (const char *const monitor_type, void *private_data)
 
static void cancel_available_timer (struct cc_core_instance *core_instance)
 
static int cc_active (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static int cc_agent_callback_helper (void *obj, void *args, int flags)
 
static struct ast_cc_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
 
static void initialize_cc_devstate_map (struct ast_config *cc_config)
 
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 (struct ast_config *cc_config)
 
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_config (void)
 
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 = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .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 = AST_RWLIST_HEAD_INIT_VALUE
 
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 = AST_RWLIST_HEAD_INIT_VALUE
 
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 int global_enabled
 
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.

Macro Definition Documentation

◆ CC_ACTIVE_DEVSTATE_DEFAULT

#define CC_ACTIVE_DEVSTATE_DEFAULT   AST_DEVICE_INUSE

Definition at line 571 of file ccss.c.

◆ CC_AVAILABLE_DEVSTATE_DEFAULT

#define CC_AVAILABLE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 568 of file ccss.c.

◆ CC_CALLEE_READY_DEVSTATE_DEFAULT

#define CC_CALLEE_READY_DEVSTATE_DEFAULT   AST_DEVICE_RINGING

Definition at line 572 of file ccss.c.

◆ CC_CALLER_BUSY_DEVSTATE_DEFAULT

#define CC_CALLER_BUSY_DEVSTATE_DEFAULT   AST_DEVICE_ONHOLD

Definition at line 573 of file ccss.c.

◆ CC_CALLER_OFFERED_DEVSTATE_DEFAULT

#define CC_CALLER_OFFERED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 569 of file ccss.c.

◆ CC_CALLER_REQUESTED_DEVSTATE_DEFAULT

#define CC_CALLER_REQUESTED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 570 of file ccss.c.

◆ CC_COMPLETE_DEVSTATE_DEFAULT

#define CC_COMPLETE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 575 of file ccss.c.

◆ CC_FAILED_DEVSTATE_DEFAULT

#define CC_FAILED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 576 of file ccss.c.

◆ CC_MAX_AGENTS_DEFAULT

#define CC_MAX_AGENTS_DEFAULT   5

Definition at line 677 of file ccss.c.

◆ CC_MAX_MONITORS_DEFAULT

#define CC_MAX_MONITORS_DEFAULT   5

Definition at line 678 of file ccss.c.

◆ CC_OFFER_TIMER_DEFAULT

#define CC_OFFER_TIMER_DEFAULT   20 /* Seconds */

Definition at line 673 of file ccss.c.

◆ CC_RECALL_TIMER_DEFAULT

#define CC_RECALL_TIMER_DEFAULT   20 /* Seconds */

Definition at line 676 of file ccss.c.

◆ CC_RECALLING_DEVSTATE_DEFAULT

#define CC_RECALLING_DEVSTATE_DEFAULT   AST_DEVICE_RINGING

Definition at line 574 of file ccss.c.

◆ CCBS_AVAILABLE_TIMER_DEFAULT

#define CCBS_AVAILABLE_TIMER_DEFAULT   4800 /* Seconds */

Definition at line 675 of file ccss.c.

◆ CCNR_AVAILABLE_TIMER_DEFAULT

#define CCNR_AVAILABLE_TIMER_DEFAULT   7200 /* Seconds */

Definition at line 674 of file ccss.c.

◆ GLOBAL_CC_MAX_REQUESTS_DEFAULT

#define GLOBAL_CC_MAX_REQUESTS_DEFAULT   20

Definition at line 679 of file ccss.c.

◆ RETURN_IF_NOT_ENABLED

#define RETURN_IF_NOT_ENABLED (   rc)

Definition at line 120 of file ccss.c.

121 { \
122 if (!global_enabled) { \
123 ast_debug(3, "CCSS disabled globally\n"); \
124 return rc; \
125 } \
126})
static int global_enabled
Definition ccss.c:118

Enumeration Type Documentation

◆ cc_state

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

196 {
197 /*! Entered when it is determined that CCSS may be used for the call */
199 /*! Entered when a CCSS agent has offered CCSS to a caller */
201 /*! Entered when a CCSS agent confirms that a caller has
202 * requested CCSS */
204 /*! Entered when a CCSS monitor confirms acknowledgment of an
205 * outbound CCSS request */
206 CC_ACTIVE,
207 /*! Entered when a CCSS monitor alerts the core that the called party
208 * has become available */
210 /*! Entered when a CCSS agent alerts the core that the calling party
211 * may not be recalled because he is unavailable
212 */
214 /*! Entered when a CCSS agent alerts the core that the calling party
215 * is attempting to recall the called party
216 */
218 /*! Entered when an application alerts the core that the calling party's
219 * recall attempt has had a call progress response indicated
220 */
222 /*! Entered any time that something goes wrong during the process, thus
223 * resulting in the failure of the attempted CCSS transaction. Note also
224 * that cancellations of CC are treated as failures.
225 */
226 CC_FAILED,
227};
@ CC_COMPLETE
Definition ccss.c:221
@ CC_CALLEE_READY
Definition ccss.c:209
@ CC_CALLER_OFFERED
Definition ccss.c:200
@ CC_ACTIVE
Definition ccss.c:206
@ CC_FAILED
Definition ccss.c:226
@ CC_CALLER_BUSY
Definition ccss.c:213
@ CC_AVAILABLE
Definition ccss.c:198
@ CC_RECALLING
Definition ccss.c:217
@ CC_CALLER_REQUESTED
Definition ccss.c:203

◆ match_flags

Enumerator
MATCH_NO_REQUEST 
MATCH_REQUEST 

Definition at line 488 of file ccss.c.

488 {
489 /* Only match agents that have not yet
490 * made a CC request
491 */
492 MATCH_NO_REQUEST = (1 << 0),
493 /* Only match agents that have made
494 * a CC request
495 */
496 MATCH_REQUEST = (1 << 1),
497};
@ MATCH_REQUEST
Definition ccss.c:496
@ MATCH_NO_REQUEST
Definition ccss.c:492

Function Documentation

◆ __ast_cc_config_params_init()

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

700{
701 struct ast_cc_config_params *params;
702
704
705 params = __ast_malloc(sizeof(*params), file, line, function);
706 if (!params) {
707 return NULL;
708 }
709
711 return params;
712}
void * __ast_malloc(size_t size, const char *file, int lineno, const char *func) attribute_malloc
Definition astmm.c:1628
void ast_cc_default_config_params(struct ast_cc_config_params *params)
Set the specified CC config params to default values.
Definition ccss.c:694
#define RETURN_IF_NOT_ENABLED(rc)
Definition ccss.c:120
#define NULL
Definition resample.c:96

References __ast_malloc(), ast_cc_default_config_params(), NULL, and RETURN_IF_NOT_ENABLED.

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4792 of file ccss.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4792 of file ccss.c.

◆ agent_destroy()

static void agent_destroy ( void *  data)
static

Definition at line 2573 of file ccss.c.

2574{
2575 struct ast_cc_agent *agent = data;
2576
2577 if (agent->callbacks) {
2578 agent->callbacks->destructor(agent);
2579 }
2581}
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition ccss.c:714
void(* destructor)(struct ast_cc_agent *agent)
Destroy private data on the agent.
Definition ccss.h:1035
const struct ast_cc_agent_callbacks * callbacks
Definition ccss.h:817
struct ast_cc_config_params * cc_params
Definition ccss.h:822

References ast_cc_config_params_destroy(), ast_cc_agent::callbacks, ast_cc_agent::cc_params, and ast_cc_agent_callbacks::destructor.

Referenced by cc_agent_init().

◆ agent_policy_to_str()

static const char * agent_policy_to_str ( enum ast_cc_agent_policies  policy)
static

Definition at line 749 of file ccss.c.

750{
751 switch (policy) {
753 return "never";
755 return "native";
757 return "generic";
758 default:
759 /* This should never happen... */
760 return "";
761 }
762}
@ AST_CC_AGENT_NEVER
Definition ccss.h:49
@ AST_CC_AGENT_GENERIC
Definition ccss.h:53
@ AST_CC_AGENT_NATIVE
Definition ccss.h:51

References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, and AST_CC_AGENT_NEVER.

Referenced by ast_cc_get_param().

◆ ast_cc_agent_accept_request()

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

3808{
3809 va_list ap;
3810 int res;
3811
3813
3814 va_start(ap, debug);
3816 va_end(ap);
3817 return res;
3818}
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition ccss.c:3346
static int debug
Global debug status.
Definition res_xmpp.c:570

References CC_CALLER_REQUESTED, cc_request_state_change(), dialed_cc_interfaces::core_id, debug, and RETURN_IF_NOT_ENABLED.

Referenced by ccreq_exec().

◆ ast_cc_agent_callback()

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

473{
474 struct cc_callback_helper helper = {.function = function, .args = args, .type = type};
475 struct cc_core_instance *core_instance;
476
478
479 if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper,
480 "Calling provided agent callback function"))) {
481 struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent");
482 cc_unref(core_instance, "agent callback done with the core_instance");
483 return agent;
484 }
485 return NULL;
486}
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
Definition astobj2.h:1696
static void * cc_unref(void *obj, const char *debug)
Definition ccss.c:165
static void * cc_ref(void *obj, const char *debug)
Definition ccss.c:159
static struct ao2_container * cc_core_instances
Definition ccss.c:342
static int cc_agent_callback_helper(void *obj, void *args, int flags)
Definition ccss.c:460
static const char type[]
static struct @519 args
ao2_callback_fn * function
Definition ccss.c:455
struct ast_cc_agent * agent
Definition ccss.c:356

References cc_core_instance::agent, ao2_t_callback, args, cc_agent_callback_helper(), cc_core_instances, cc_ref(), cc_unref(), cc_callback_helper::function, NULL, RETURN_IF_NOT_ENABLED, and type.

◆ ast_cc_agent_caller_available()

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

3860{
3861 va_list ap;
3862 int res;
3863
3865
3866 va_start(ap, debug);
3867 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3868 va_end(ap);
3869 return res;
3870}

References CC_ACTIVE, cc_request_state_change(), dialed_cc_interfaces::core_id, debug, and RETURN_IF_NOT_ENABLED.

Referenced by generic_agent_devstate_cb().

◆ ast_cc_agent_caller_busy()

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

3847{
3848 va_list ap;
3849 int res;
3850
3852
3853 va_start(ap, debug);
3854 res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap);
3855 va_end(ap);
3856 return res;
3857}

References CC_CALLER_BUSY, cc_request_state_change(), dialed_cc_interfaces::core_id, debug, and RETURN_IF_NOT_ENABLED.

Referenced by cc_generic_agent_recall().

◆ ast_cc_agent_recalling()

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

3873{
3874 va_list ap;
3875 int res;
3876
3878
3879 va_start(ap, debug);
3880 res = cc_request_state_change(CC_RECALLING, core_id, debug, ap);
3881 va_end(ap);
3882 return res;
3883}

References CC_RECALLING, cc_request_state_change(), dialed_cc_interfaces::core_id, debug, and RETURN_IF_NOT_ENABLED.

Referenced by generic_recall().

◆ ast_cc_agent_register()

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

1248{
1249 struct cc_agent_backend *backend;
1250
1252
1253 backend = ast_calloc(1, sizeof(*backend));
1254 if (!backend) {
1255 return -1;
1256 }
1257
1258 backend->callbacks = callbacks;
1262 return 0;
1263}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#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.
#define AST_RWLIST_INSERT_TAIL
struct @506 callbacks
const struct ast_cc_agent_callbacks * callbacks
Definition ccss.c:1242
struct cc_agent_backend * next
Definition ccss.c:1241

References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cc_agent_backend::callbacks, callbacks, cc_agent_backend::next, and RETURN_IF_NOT_ENABLED.

Referenced by load_module(), and load_module().

◆ ast_cc_agent_set_interfaces_chanvar()

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

3655{
3656 struct ast_datastore *recall_datastore;
3657 struct cc_monitor_tree *interface_tree;
3658 struct ast_cc_monitor *monitor;
3659 struct cc_recall_ds_data *recall_data;
3660 struct ast_str *str = ast_str_create(64);
3661 int core_id;
3662
3664
3665 if (!str) {
3666 return -1;
3667 }
3668
3669 ast_channel_lock(chan);
3670 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3671 ast_channel_unlock(chan);
3672 ast_free(str);
3673 return -1;
3674 }
3675 recall_data = recall_datastore->data;
3676 interface_tree = recall_data->interface_tree;
3677 core_id = recall_data->core_id;
3678 ast_channel_unlock(chan);
3679
3680 AST_LIST_LOCK(interface_tree);
3681 monitor = AST_LIST_FIRST(interface_tree);
3683 AST_LIST_UNLOCK(interface_tree);
3684
3685 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3686 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3687 core_id, ast_str_buffer(str));
3688
3689 ast_free(str);
3690 return 0;
3691}
const char * str
Definition app_jack.c:150
#define ast_free(a)
Definition astmm.h:180
static const struct ast_datastore_info recall_ds_info
Definition ccss.c:3417
static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str **str)
Definition ccss.c:3611
static int cc_logger_level
Definition ccss.c:149
#define ast_channel_lock(chan)
Definition channel.h:2982
#define ast_channel_unlock(chan)
Definition channel.h:2983
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:2389
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
#define AST_LIST_LOCK(head)
Locks a list.
Definition linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
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.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
Structure for a data store object.
Definition datastore.h:64
void * data
Definition datastore.h:66
Support for dynamic strings.
Definition strings.h:623
The "tree" of interfaces that is dialed.
Definition ccss.c:339
struct cc_monitor_tree * interface_tree
Definition ccss.c:3393

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_free, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_str_buffer(), ast_str_create, build_cc_interfaces_chanvar(), cc_logger_level, cc_recall_ds_data::core_id, ast_datastore::data, cc_recall_ds_data::interface_tree, NULL, pbx_builtin_setvar_helper(), recall_ds_info, RETURN_IF_NOT_ENABLED, and str.

Referenced by generic_recall().

◆ ast_cc_agent_status_response()

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

4149{
4151 struct cc_core_instance *core_instance;
4152 int res;
4153
4155
4156 args = ast_calloc(1, sizeof(*args));
4157 if (!args) {
4158 return -1;
4159 }
4160
4161 core_instance = find_cc_core_instance(core_id);
4162 if (!core_instance) {
4163 ast_free(args);
4164 return -1;
4165 }
4166
4167 args->core_instance = core_instance;
4168 args->devstate = devstate;
4169
4171 if (res) {
4172 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4173 ast_free(args);
4174 }
4175 return res;
4176}
static struct ast_taskprocessor * cc_core_taskprocessor
Definition ccss.c:141
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition ccss.c:447
static int cc_status_response(void *data)
Definition ccss.c:4127
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.

References args, ast_calloc, ast_free, ast_taskprocessor_push(), cc_core_taskprocessor, cc_status_response(), cc_unref(), cc_core_instance::core_id, find_cc_core_instance(), and RETURN_IF_NOT_ENABLED.

Referenced by cc_generic_agent_status_request().

◆ ast_cc_agent_unregister()

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

1266{
1267 struct cc_agent_backend *backend;
1268
1270
1273 if (backend->callbacks == callbacks) {
1275 ast_free(backend);
1276 break;
1277 }
1278 }
1281}
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_TRAVERSE_SAFE_END

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cc_agent_backend::callbacks, callbacks, cc_agent_backend::next, and RETURN_IF_NOT_ENABLED.

Referenced by __unload_module(), and unload_module().

◆ ast_cc_available_timer_expire()

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

1524{
1525 struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data;
1526 int res;
1527
1529
1530 monitor->available_timer_id = -1;
1531 res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor");
1532 cc_unref(monitor, "Unref reference from scheduler\n");
1533 return res;
1534}
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:3988
char device_name[1]
Definition ccss.h:802
struct ast_cc_interface * interface
Definition ccss.h:480
int core_id
Definition ccss.h:494
int available_timer_id
Definition ccss.h:513

References ast_cc_monitor_failed(), ast_cc_monitor::available_timer_id, cc_unref(), ast_cc_monitor::core_id, ast_cc_interface::device_name, ast_cc_monitor::interface, and RETURN_IF_NOT_ENABLED.

Referenced by cc_generic_monitor_request_cc().

◆ ast_cc_build_frame()

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

4239{
4240 struct cc_control_payload *payload;
4241
4243
4244 payload = ast_calloc(1, sizeof(*payload));
4245 if (!payload) {
4246 return -1;
4247 }
4248 if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) {
4249 /* Something screwed up, we can't make a frame with this */
4250 ast_free(payload);
4251 return -1;
4252 }
4255 frame->data.ptr = payload;
4256 frame->datalen = sizeof(*payload);
4257 frame->mallocd = AST_MALLOCD_DATA;
4258 return 0;
4259}
enum ast_cc_service_type service
Definition ccss.c:399
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)
Definition ccss.c:4178
#define AST_MALLOCD_DATA
@ AST_FRAME_CONTROL
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@239 data
The payload for an AST_CONTROL_CC frame.
Definition ccss.c:237
const char * monitor_type
The type of monitor to allocate.
Definition ccss.c:255
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition ccss.c:308
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition ccss.c:320
void * private_data
Private data allocated by the callee.
Definition ccss.c:272

References ast_calloc, AST_CONTROL_CC, AST_FRAME_CONTROL, ast_free, AST_MALLOCD_DATA, cc_build_payload(), ast_frame::data, ast_frame::datalen, cc_control_payload::device_name, cc_control_payload::dialstring, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, cc_control_payload::monitor_type, cc_control_payload::private_data, ast_frame::ptr, RETURN_IF_NOT_ENABLED, service, and ast_frame::subclass.

Referenced by ast_queue_cc_frame().

◆ ast_cc_busy_interface()

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

4298{
4299 struct cc_control_payload payload;
4300
4302
4303 if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) {
4304 /* Something screwed up. Don't try to handle this payload */
4306 return;
4307 }
4308 ast_handle_cc_control_frame(inbound, NULL, &payload);
4309}
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:2334
static void call_destructor_with_no_monitor(const char *const monitor_type, void *private_data)
Definition ccss.c:2233
@ AST_CC_CCBS
Definition ccss.h:36

References AST_CC_CCBS, ast_handle_cc_control_frame(), call_destructor_with_no_monitor(), cc_build_payload(), cc_control_payload::device_name, cc_control_payload::dialstring, cc_control_payload::monitor_type, NULL, cc_control_payload::private_data, and RETURN_IF_NOT_ENABLED.

Referenced by dial_exec_full().

◆ ast_cc_call_failed()

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

4262{
4263 char device_name[AST_CHANNEL_NAME];
4264 struct cc_control_payload payload;
4265 struct ast_cc_config_params *cc_params;
4266
4268
4270 /* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call
4271 * failing is something other than busy or congestion
4272 */
4273 return;
4274 }
4275
4277 if (!cc_params) {
4278 return;
4279 }
4281 /* This sort of CCBS only works if using generic CC. For native, we would end up sending
4282 * a CC request for a non-existent call. The far end will reject this every time
4283 */
4284 return;
4285 }
4286
4287 ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
4288 if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
4289 dialstring, AST_CC_CCBS, NULL, &payload)) {
4290 /* Something screwed up, we can't make a frame with this */
4291 return;
4292 }
4293 ast_handle_cc_control_frame(incoming, outgoing, &payload);
4294}
#define AST_CAUSE_CONGESTION
Definition causes.h:153
#define AST_CAUSE_BUSY
Definition causes.h:149
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition ccss.c:900
#define AST_CC_GENERIC_MONITOR_TYPE
Definition ccss.h:455
@ AST_CC_MONITOR_GENERIC
Definition ccss.h:83
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:10544
int ast_channel_hangupcause(const struct ast_channel *chan)
#define AST_CHANNEL_NAME
Definition channel.h:173
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:10518

References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CC_CCBS, AST_CC_GENERIC_MONITOR_TYPE, AST_CC_MONITOR_GENERIC, ast_channel_get_cc_config_params(), ast_channel_get_device_name(), ast_channel_hangupcause(), AST_CHANNEL_NAME, ast_get_cc_monitor_policy(), ast_handle_cc_control_frame(), cc_build_payload(), cc_control_payload::device_name, NULL, and RETURN_IF_NOT_ENABLED.

Referenced by dial_exec_full().

◆ ast_cc_call_init()

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

2430{
2431 /* There are three situations to deal with here:
2432 *
2433 * 1. The channel does not have a dialed_cc_interfaces datastore on
2434 * it. This means that this is the first time that Dial has
2435 * been called. We need to create/initialize the datastore.
2436 *
2437 * 2. The channel does have a cc_interface datastore on it and
2438 * the "ignore" indicator is 0. This means that a Local channel
2439 * was called by a "parent" dial. We can check the datastore's
2440 * parent field to see who the root of this particular dial tree
2441 * is.
2442 *
2443 * 3. The channel does have a cc_interface datastore on it and
2444 * the "ignore" indicator is 1. This means that a second Dial call
2445 * is being made from an extension. In this case, we do not
2446 * want to make any additions/modifications to the datastore. We
2447 * will instead set a flag to indicate that CCSS is completely
2448 * disabled for this Dial attempt.
2449 */
2450
2451 struct ast_datastore *cc_interfaces_datastore;
2453 struct ast_cc_monitor *monitor;
2454 struct ast_cc_config_params *cc_params;
2455
2456 if (!global_enabled) {
2457 ast_debug(3, "CCSS disabled globally\n");
2458 *ignore_cc = 1;
2459 return 0;
2460 }
2461
2462 ast_channel_lock(chan);
2463
2464 cc_params = ast_channel_get_cc_config_params(chan);
2465 if (!cc_params) {
2466 ast_channel_unlock(chan);
2467 return -1;
2468 }
2469 if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) {
2470 /* We can't offer CC to this caller anyway, so don't bother with CC on this call
2471 */
2472 *ignore_cc = 1;
2473 ast_channel_unlock(chan);
2474 ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", ast_channel_name(chan));
2475 return 0;
2476 }
2477
2478 if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2479 /* Situation 1 has occurred */
2480 ast_channel_unlock(chan);
2481 return cc_interfaces_datastore_init(chan);
2482 }
2483 interfaces = cc_interfaces_datastore->data;
2484 ast_channel_unlock(chan);
2485
2486 if (interfaces->ignore) {
2487 /* Situation 3 has occurred */
2488 *ignore_cc = 1;
2489 ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n");
2490 return 0;
2491 }
2492
2493 /* Situation 2 has occurred */
2494 if (!(monitor = cc_extension_monitor_init(ast_channel_exten(chan),
2495 ast_channel_context(chan),
2496 interfaces->dial_parent_id))) {
2497 return -1;
2498 }
2499 monitor->core_id = interfaces->core_id;
2500 AST_LIST_LOCK(interfaces->interface_tree);
2501 cc_ref(monitor, "monitor tree's reference to the monitor");
2502 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
2503 AST_LIST_UNLOCK(interfaces->interface_tree);
2504 interfaces->dial_parent_id = monitor->id;
2505 cc_unref(monitor, "Unref monitor's allocation reference");
2506 return 0;
2507}
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition ccss.c:2006
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition ccss.c:883
static struct ast_cc_monitor * cc_extension_monitor_init(const char *const exten, const char *const context, const unsigned int parent_id)
Definition ccss.c:2108
static int cc_interfaces_datastore_init(struct ast_channel *chan)
Definition ccss.c:2157
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
static struct ao2_container * interfaces
Container for registered format interfaces.
Definition format.c:65
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
unsigned int id
Definition ccss.h:485

References AST_CC_AGENT_NEVER, ast_channel_context(), ast_channel_datastore_find(), ast_channel_exten(), ast_channel_get_cc_config_params(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_get_cc_agent_policy(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log_dynamic_level, cc_extension_monitor_init(), cc_interfaces_datastore_init(), cc_logger_level, cc_ref(), cc_unref(), ast_cc_monitor::core_id, ast_datastore::data, dialed_cc_interfaces_info, global_enabled, ast_cc_monitor::id, interfaces, and NULL.

Referenced by dial_exec_full().

◆ ast_cc_callback()

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

4312{
4313 const struct ast_channel_tech *chantech;
4314
4316
4317 chantech = ast_get_channel_tech(tech);
4318 if (chantech && chantech->cc_callback) {
4319 chantech->cc_callback(inbound, dest, callback);
4320 }
4321
4322 return 0;
4323}
const struct ast_channel_tech * ast_get_channel_tech(const char *name)
Get a channel technology structure by name.
Definition channel.c:592
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648
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:847

References ast_get_channel_tech(), callback(), ast_channel_tech::cc_callback, and RETURN_IF_NOT_ENABLED.

Referenced by dial_exec_full().

◆ ast_cc_completed()

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

3886{
3887 struct ast_datastore *recall_datastore;
3888 struct cc_recall_ds_data *recall_data;
3889 int core_id;
3890 va_list ap;
3891 int res;
3892
3894
3895 ast_channel_lock(chan);
3896 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3897 /* Silly! Why did you call this function if there's no recall DS? */
3898 ast_channel_unlock(chan);
3899 return -1;
3900 }
3901 recall_data = recall_datastore->data;
3902 if (recall_data->nested || recall_data->ignore) {
3903 /* If this is being called from a nested Dial, it is too
3904 * early to determine if the recall has actually completed.
3905 * The outermost dial is the only one with the authority to
3906 * declare the recall to be complete.
3907 *
3908 * Similarly, if this function has been called when the
3909 * recall has progressed beyond the first dial, this is not
3910 * a legitimate time to declare the recall to be done. In fact,
3911 * that should have been done already.
3912 */
3913 ast_channel_unlock(chan);
3914 return -1;
3915 }
3916 core_id = recall_data->core_id;
3917 ast_channel_unlock(chan);
3918 va_start(ap, debug);
3920 va_end(ap);
3921 return res;
3922}

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, CC_COMPLETE, cc_request_state_change(), cc_recall_ds_data::core_id, ast_datastore::data, debug, cc_recall_ds_data::ignore, cc_recall_ds_data::nested, NULL, recall_ds_info, and RETURN_IF_NOT_ENABLED.

Referenced by wait_for_answer().

◆ ast_cc_config_params_destroy()

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

715{
716 ast_free(params);
717}

References ast_free.

Referenced by agent_destroy(), ast_channel_cc_params_init(), cc_interface_destroy(), channel_cc_params_destroy(), dahdi_create_channel_range(), destroy_dahdi_pvt(), process_dahdi(), and setup_dahdi().

◆ ast_cc_copy_config_params()

void ast_cc_copy_config_params ( struct ast_cc_config_params dest,
const struct ast_cc_config_params src 
)

copy CCSS configuration parameters from one structure to another

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

877{
878 if (dest && src) {
879 *dest = *src;
880 }
881}

Referenced by ast_channel_cc_params_init(), cc_agent_init(), cc_build_payload(), cc_device_monitor_init(), channel_cc_params_copy(), dahdi_new(), deep_copy_dahdi_chan_conf(), duplicate_pseudo(), and mkintf().

◆ ast_cc_default_config_params()

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

695{
696 *params = cc_default_params;
697}
static const struct ast_cc_config_params cc_default_params
Definition ccss.c:681

References cc_default_params.

Referenced by __ast_cc_config_params_init().

◆ ast_cc_extension_monitor_add_dialstring()

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

2023{
2024 struct ast_datastore *cc_datastore;
2025 struct dialed_cc_interfaces *cc_interfaces;
2026 struct ast_cc_monitor *monitor;
2027 struct extension_monitor_pvt *extension_pvt;
2028 struct extension_child_dialstring *child_dialstring;
2029 struct cc_monitor_tree *interface_tree;
2030 int id;
2031
2033
2034 ast_channel_lock(incoming);
2035 if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) {
2036 ast_channel_unlock(incoming);
2037 return;
2038 }
2039
2040 cc_interfaces = cc_datastore->data;
2041 interface_tree = cc_interfaces->interface_tree;
2042 id = cc_interfaces->dial_parent_id;
2043 ast_channel_unlock(incoming);
2044
2045 AST_LIST_LOCK(interface_tree);
2046 AST_LIST_TRAVERSE(interface_tree, monitor, next) {
2047 if (monitor->id == id) {
2048 break;
2049 }
2050 }
2051
2052 if (!monitor) {
2053 AST_LIST_UNLOCK(interface_tree);
2054 return;
2055 }
2056
2057 extension_pvt = monitor->private_data;
2058 if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) {
2059 AST_LIST_UNLOCK(interface_tree);
2060 return;
2061 }
2062 ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring));
2063 ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name));
2064 child_dialstring->is_valid = 1;
2065 AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next);
2066 AST_LIST_UNLOCK(interface_tree);
2067}
enum queue_result id
Definition app_queue.c:1771
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
void * private_data
Data that is private to a monitor technology.
Definition ccss.h:527
struct cc_monitor_tree * interface_tree
Definition ccss.c:1946
unsigned int dial_parent_id
Definition ccss.c:1919
Data regarding an extension monitor's child's dialstrings.
Definition ccss.c:1777
char device_name[AST_CHANNEL_NAME]
The name of the device being dialed.
Definition ccss.c:1812
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition ccss.c:1827
char original_dialstring[AST_CHANNEL_NAME]
the original dialstring used to call a particular device
Definition ccss.c:1793
Private data for an extension monitor.
Definition ccss.c:1834
struct extension_monitor_pvt::@348 child_dialstrings

References ast_calloc, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, extension_monitor_pvt::child_dialstrings, ast_datastore::data, extension_child_dialstring::device_name, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces_info, id, ast_cc_monitor::id, dialed_cc_interfaces::interface_tree, extension_child_dialstring::is_valid, NULL, extension_child_dialstring::original_dialstring, ast_cc_monitor::private_data, and RETURN_IF_NOT_ENABLED.

Referenced by dial_exec_full().

◆ ast_cc_failed()

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

3925{
3926 va_list ap;
3927 int res;
3928
3930
3931 va_start(ap, debug);
3932 res = cc_request_state_change(CC_FAILED, core_id, debug, ap);
3933 va_end(ap);
3934 return res;
3935}

References CC_FAILED, cc_request_state_change(), cc_recall_ds_data::core_id, debug, and RETURN_IF_NOT_ENABLED.

Referenced by cancel_available_timer(), cc_caller_offered(), cc_caller_requested(), cc_monitor_failed(), cccancel_exec(), ccreq_exec(), generic_recall(), kill_cores(), offer_timer_expire(), request_cc(), suspend(), unsuspend(), and wait_for_answer().

◆ ast_cc_get_current_core_id()

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

2515{
2516 struct ast_datastore *datastore;
2517 struct dialed_cc_interfaces *cc_interfaces;
2518 int core_id_return;
2519
2521
2522 ast_channel_lock(chan);
2523 if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2524 ast_channel_unlock(chan);
2525 return -1;
2526 }
2527
2528 cc_interfaces = datastore->data;
2529 core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id;
2530 ast_channel_unlock(chan);
2531 return core_id_return;
2532
2533}

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, dialed_cc_interfaces::core_id, ast_datastore::data, dialed_cc_interfaces_info, dialed_cc_interfaces::ignore, NULL, and RETURN_IF_NOT_ENABLED.

◆ ast_cc_get_monitor_by_recall_core_id()

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

3543{
3544 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3545 struct ast_cc_monitor *monitor_iter;
3546
3548
3549 if (!core_instance) {
3550 return NULL;
3551 }
3552
3553 AST_LIST_LOCK(core_instance->monitors);
3554 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
3555 if (!strcmp(monitor_iter->interface->device_name, device_name)) {
3556 /* Found a monitor. */
3557 cc_ref(monitor_iter, "Hand the requester of the monitor a reference");
3558 break;
3559 }
3560 }
3561 AST_LIST_UNLOCK(core_instance->monitors);
3562 cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id");
3563 return monitor_iter;
3564}
struct ast_cc_monitor * next
Definition ccss.h:528
struct cc_monitor_tree * monitors
Definition ccss.c:360

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, cc_ref(), cc_unref(), cc_core_instance::core_id, ast_cc_interface::device_name, find_cc_core_instance(), ast_cc_monitor::interface, cc_core_instance::monitors, ast_cc_monitor::next, NULL, and RETURN_IF_NOT_ENABLED.

◆ ast_cc_get_param()

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

782{
783 const char *value = NULL;
784
785 if (!strcasecmp(name, "cc_callback_sub")) {
787 } else if (!strcasecmp(name, "cc_agent_policy")) {
789 } else if (!strcasecmp(name, "cc_monitor_policy")) {
791 } else if (!strcasecmp(name, "cc_agent_dialstring")) {
793 }
794 if (value) {
795 ast_copy_string(buf, value, buf_len);
796 return 0;
797 }
798
799 /* The rest of these are all ints of some sort and require some
800 * snprintf-itude
801 */
802
803 if (!strcasecmp(name, "cc_offer_timer")) {
804 snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params));
805 } else if (!strcasecmp(name, "ccnr_available_timer")) {
806 snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params));
807 } else if (!strcasecmp(name, "ccbs_available_timer")) {
808 snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params));
809 } else if (!strcasecmp(name, "cc_max_agents")) {
810 snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params));
811 } else if (!strcasecmp(name, "cc_max_monitors")) {
812 snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params));
813 } else if (!strcasecmp(name, "cc_recall_timer")) {
814 snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params));
815 } else {
816 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
817 return -1;
818 }
819
820 return 0;
821}
#define ast_log
Definition astobj2.c:42
unsigned int ast_get_cc_recall_timer(struct ast_cc_config_params *config)
Get the cc_recall_timer.
Definition ccss.c:947
static const char * agent_policy_to_str(enum ast_cc_agent_policies policy)
Definition ccss.c:749
unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
Get the cc_offer_timer.
Definition ccss.c:917
unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
Get the ccbs_available_timer.
Definition ccss.c:962
unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
Get the ccnr_available_timer.
Definition ccss.c:932
unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
Get the cc_max_agents.
Definition ccss.c:991
const char * ast_get_cc_callback_sub(struct ast_cc_config_params *config)
Get the name of the callback subroutine.
Definition ccss.c:1011
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition ccss.c:1001
static const char * monitor_policy_to_str(enum ast_cc_monitor_policies policy)
Definition ccss.c:764
const char * ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
Get the cc_agent_dialstring.
Definition ccss.c:977
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static const char name[]
Definition format_mp3.c:68
#define LOG_WARNING
int value
Definition syslog.c:37

References agent_policy_to_str(), 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(), ast_get_ccnr_available_timer(), ast_log, buf, LOG_WARNING, monitor_policy_to_str(), name, NULL, and value.

Referenced by acf_cc_read().

◆ ast_cc_is_config_param()

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

863{
864 return (!strcasecmp(name, "cc_agent_policy") ||
865 !strcasecmp(name, "cc_monitor_policy") ||
866 !strcasecmp(name, "cc_offer_timer") ||
867 !strcasecmp(name, "ccnr_available_timer") ||
868 !strcasecmp(name, "ccbs_available_timer") ||
869 !strcasecmp(name, "cc_max_agents") ||
870 !strcasecmp(name, "cc_max_monitors") ||
871 !strcasecmp(name, "cc_callback_sub") ||
872 !strcasecmp(name, "cc_agent_dialstring") ||
873 !strcasecmp(name, "cc_recall_timer"));
874}

References name.

Referenced by process_dahdi().

◆ ast_cc_is_enabled()

int ast_cc_is_enabled ( void  )

Determine if CCSS is enabled.

Since
23.2.0
22.8.0
20.18.0
Return values
0Not enabled.
1Enabled

Definition at line 4540 of file ccss.c.

4541{
4542 return global_enabled;
4543}

References global_enabled.

Referenced by ast_channel_get_cc_config_params(), ast_unreal_call_setup(), ast_unreal_new_channels(), and local_call().

◆ ast_cc_is_recall()

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

3460{
3461 struct ast_datastore *recall_datastore;
3462 struct cc_recall_ds_data *recall_data;
3463 struct cc_monitor_tree *interface_tree;
3464 char device_name[AST_CHANNEL_NAME];
3465 struct ast_cc_monitor *device_monitor;
3466 int core_id_candidate;
3467
3469
3471
3472 *core_id = -1;
3473
3474 ast_channel_lock(chan);
3475 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3476 /* Obviously not a recall if the datastore isn't present */
3477 ast_channel_unlock(chan);
3478 return 0;
3479 }
3480
3481 recall_data = recall_datastore->data;
3482
3483 if (recall_data->ignore) {
3484 /* Though this is a recall, the call to this particular interface is not part of the
3485 * recall either because this is a call forward or because this is not the first
3486 * invocation of Dial during this call
3487 */
3488 ast_channel_unlock(chan);
3489 return 0;
3490 }
3491
3492 if (!recall_data->nested) {
3493 /* If the nested flag is not set, then this means that
3494 * the channel passed to this function is the caller making
3495 * the recall. This means that we shouldn't look through
3496 * the monitor tree for the channel because it shouldn't be
3497 * there. However, this is a recall though, so return true.
3498 */
3499 *core_id = recall_data->core_id;
3500 ast_channel_unlock(chan);
3501 return 1;
3502 }
3503
3504 if (ast_strlen_zero(monitor_type)) {
3505 /* If someone passed a NULL or empty monitor type, then it is clear
3506 * the channel they passed in was an incoming channel, and so searching
3507 * the list of dialed interfaces is not going to be helpful. Just return
3508 * false immediately.
3509 */
3510 ast_channel_unlock(chan);
3511 return 0;
3512 }
3513
3514 interface_tree = recall_data->interface_tree;
3515 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
3516 /* We grab the value of the recall_data->core_id so that we
3517 * can unlock the channel before we start looking through the
3518 * interface list. That way we don't have to worry about a possible
3519 * clash between the channel lock and the monitor tree lock.
3520 */
3521 core_id_candidate = recall_data->core_id;
3522 ast_channel_unlock(chan);
3523
3524 /*
3525 * Now we need to find out if the channel device name
3526 * is in the list of interfaces in the called tree.
3527 */
3528 AST_LIST_LOCK(interface_tree);
3529 AST_LIST_TRAVERSE(interface_tree, device_monitor, next) {
3530 if (!strcmp(device_monitor->interface->device_name, device_name) &&
3531 !strcmp(device_monitor->interface->monitor_type, monitor_type)) {
3532 /* BOOM! Device is in the tree! We have a winner! */
3533 *core_id = core_id_candidate;
3534 AST_LIST_UNLOCK(interface_tree);
3535 return 1;
3536 }
3537 }
3538 AST_LIST_UNLOCK(interface_tree);
3539 return 0;
3540}
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
const char * monitor_type
The type of monitor that should be used for this interface.
Definition ccss.h:793
#define ast_assert(a)
Definition utils.h:779

References ast_assert, ast_channel_datastore_find(), ast_channel_get_device_name(), ast_channel_lock, AST_CHANNEL_NAME, ast_channel_unlock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_cc_monitor::core_id, cc_recall_ds_data::core_id, ast_datastore::data, ast_cc_interface::device_name, cc_recall_ds_data::ignore, ast_cc_monitor::interface, cc_recall_ds_data::interface_tree, ast_cc_interface::monitor_type, cc_recall_ds_data::nested, ast_cc_monitor::next, NULL, recall_ds_info, and RETURN_IF_NOT_ENABLED.

Referenced by cc_core_init_instance(), and wait_for_answer().

◆ ast_cc_monitor_callee_available()

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

3834{
3835 va_list ap;
3836 int res;
3837
3839
3840 va_start(ap, debug);
3841 res = cc_request_state_change(CC_CALLEE_READY, core_id, debug, ap);
3842 va_end(ap);
3843 return res;
3844}

References CC_CALLEE_READY, cc_request_state_change(), dialed_cc_interfaces::core_id, debug, and RETURN_IF_NOT_ENABLED.

Referenced by cc_generic_monitor_destructor(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), and generic_monitor_devstate_tp_cb().

◆ ast_cc_monitor_count()

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

4439{
4440 struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,};
4441
4443
4444 ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents");
4445 ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count);
4446 return data.count;
4447}
@ OBJ_NODATA
Definition astobj2.h:1044
static int count_monitors_cb(void *obj, void *arg, int flags)
Definition ccss.c:4418
const char * device_name
Definition ccss.c:4413

References ao2_t_callback, ast_log_dynamic_level, cc_core_instances, cc_logger_level, count_monitors_cb_data::count, count_monitors_cb(), count_monitors_cb_data::device_name, name, OBJ_NODATA, RETURN_IF_NOT_ENABLED, and type.

Referenced by ast_queue_cc_frame().

◆ ast_cc_monitor_failed()

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

3989{
3990 struct ast_cc_monitor_failure_data *failure_data;
3991 int res;
3992 va_list ap;
3993
3995
3996 if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) {
3997 return -1;
3998 }
3999
4000 if (!(failure_data->device_name = ast_strdup(monitor_name))) {
4001 ast_free(failure_data);
4002 return -1;
4003 }
4004
4005 va_start(ap, debug);
4006 if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) {
4007 va_end(ap);
4008 ast_free((char *)failure_data->device_name);
4009 ast_free(failure_data);
4010 return -1;
4011 }
4012 va_end(ap);
4013
4014 failure_data->core_id = core_id;
4015
4017 if (res) {
4018 ast_free((char *)failure_data->device_name);
4019 ast_free((char *)failure_data->debug);
4020 ast_free(failure_data);
4021 }
4022 return res;
4023}
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
Definition astmm.h:278
static int cc_monitor_failed(void *data)
Definition ccss.c:3943
const char * device_name
Definition ccss.c:3938

References ast_calloc, ast_free, ast_strdup, ast_taskprocessor_push(), ast_vasprintf, cc_core_taskprocessor, cc_monitor_failed(), ast_cc_monitor_failure_data::core_id, ast_cc_monitor_failure_data::debug, debug, ast_cc_monitor_failure_data::device_name, and RETURN_IF_NOT_ENABLED.

Referenced by ast_cc_available_timer_expire().

◆ ast_cc_monitor_party_b_free()

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

4105{
4106 int res;
4107 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4108
4110
4111 if (!core_instance) {
4112 return -1;
4113 }
4114
4116 if (res) {
4117 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4118 }
4119 return res;
4120}
static int cc_party_b_free(void *data)
Definition ccss.c:4092

References ast_taskprocessor_push(), cc_core_taskprocessor, cc_party_b_free(), cc_unref(), cc_core_instance::core_id, find_cc_core_instance(), and RETURN_IF_NOT_ENABLED.

◆ ast_cc_monitor_register()

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

1187{
1188 struct cc_monitor_backend *backend;
1189
1191
1192 backend = ast_calloc(1, sizeof(*backend));
1193 if (!backend) {
1194 return -1;
1195 }
1196
1197 backend->callbacks = callbacks;
1198
1202 return 0;
1203}
const struct ast_cc_monitor_callbacks * callbacks
Definition ccss.c:1181
struct cc_monitor_backend * next
Definition ccss.c:1180

References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cc_monitor_backend::callbacks, callbacks, cc_monitor_backend::next, and RETURN_IF_NOT_ENABLED.

Referenced by load_module(), and load_module().

◆ ast_cc_monitor_request_acked()

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

3821{
3822 va_list ap;
3823 int res;
3824
3826
3827 va_start(ap, debug);
3828 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3829 va_end(ap);
3830 return res;
3831}

References CC_ACTIVE, cc_request_state_change(), dialed_cc_interfaces::core_id, debug, and RETURN_IF_NOT_ENABLED.

Referenced by cc_generic_monitor_request_cc(), and cc_stop_ringing().

◆ ast_cc_monitor_status_request()

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

4036{
4037 int res;
4038 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4039
4041
4042 if (!core_instance) {
4043 return -1;
4044 }
4045
4047 if (res) {
4048 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4049 }
4050 return res;
4051}
static int cc_status_request(void *data)
Definition ccss.c:4025

References ast_taskprocessor_push(), cc_core_taskprocessor, cc_status_request(), cc_unref(), cc_core_instance::core_id, find_cc_core_instance(), and RETURN_IF_NOT_ENABLED.

◆ ast_cc_monitor_stop_ringing()

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

4075{
4076 int res;
4077 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4078
4080
4081 if (!core_instance) {
4082 return -1;
4083 }
4084
4086 if (res) {
4087 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4088 }
4089 return res;
4090}
static int cc_stop_ringing(void *data)
Definition ccss.c:4053

References ast_taskprocessor_push(), cc_core_taskprocessor, cc_stop_ringing(), cc_unref(), cc_core_instance::core_id, find_cc_core_instance(), and RETURN_IF_NOT_ENABLED.

◆ ast_cc_monitor_unregister()

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

1223{
1224 struct cc_monitor_backend *backend;
1225
1227
1230 if (backend->callbacks == callbacks) {
1232 ast_free(backend);
1233 break;
1234 }
1235 }
1238}

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cc_monitor_backend::callbacks, callbacks, cc_monitor_backend::next, and RETURN_IF_NOT_ENABLED.

Referenced by __unload_module(), and unload_module().

◆ ast_cc_offer()

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

3781{
3782 int core_id;
3783 int res = -1;
3784 struct ast_datastore *datastore;
3785 struct dialed_cc_interfaces *cc_interfaces;
3786 char cc_is_offerable;
3787
3789
3790 ast_channel_lock(caller_chan);
3791 if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) {
3792 ast_channel_unlock(caller_chan);
3793 return res;
3794 }
3795
3796 cc_interfaces = datastore->data;
3797 cc_is_offerable = cc_interfaces->is_original_caller;
3798 core_id = cc_interfaces->core_id;
3799 ast_channel_unlock(caller_chan);
3800
3801 if (cc_is_offerable) {
3802 res = cc_offer(core_id, "CC offered to caller %s", ast_channel_name(caller_chan));
3803 }
3804 return res;
3805}
static int cc_offer(const int core_id, const char *const debug,...)
Definition ccss.c:3769
char is_original_caller
Definition ccss.c:1942

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, cc_offer(), dialed_cc_interfaces::core_id, cc_recall_ds_data::core_id, ast_datastore::data, dialed_cc_interfaces_info, dialed_cc_interfaces::is_original_caller, NULL, and RETURN_IF_NOT_ENABLED.

Referenced by ast_hangup().

◆ ast_cc_request_is_within_limits()

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

2510{
2512}
static unsigned int global_cc_max_requests
Definition ccss.c:153
static int cc_request_count
Definition ccss.c:157

References cc_request_count, and global_cc_max_requests.

Referenced by cc_caller_requested(), cc_interfaces_datastore_init(), and ccreq_exec().

◆ ast_cc_set_param()

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

825{
826 unsigned int value_as_uint;
827 if (!strcasecmp(name, "cc_agent_policy")) {
829 } else if (!strcasecmp(name, "cc_monitor_policy")) {
831 } else if (!strcasecmp(name, "cc_agent_dialstring")) {
833 } else if (!strcasecmp(name, "cc_callback_sub")) {
835 return 0;
836 }
837
838 if (sscanf(value, "%30u", &value_as_uint) != 1) {
839 return -1;
840 }
841
842 if (!strcasecmp(name, "cc_offer_timer")) {
843 ast_set_cc_offer_timer(params, value_as_uint);
844 } else if (!strcasecmp(name, "ccnr_available_timer")) {
845 ast_set_ccnr_available_timer(params, value_as_uint);
846 } else if (!strcasecmp(name, "ccbs_available_timer")) {
847 ast_set_ccbs_available_timer(params, value_as_uint);
848 } else if (!strcasecmp(name, "cc_max_agents")) {
849 ast_set_cc_max_agents(params, value_as_uint);
850 } else if (!strcasecmp(name, "cc_max_monitors")) {
851 ast_set_cc_max_monitors(params, value_as_uint);
852 } else if (!strcasecmp(name, "cc_recall_timer")) {
853 ast_set_cc_recall_timer(params, value_as_uint);
854 } else {
855 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
856 return -1;
857 }
858
859 return 0;
860}
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:888
void ast_set_cc_max_monitors(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_monitors.
Definition ccss.c:1006
void ast_set_ccbs_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccbs_available_timer.
Definition ccss.c:967
void ast_set_cc_callback_sub(struct ast_cc_config_params *config, const char *const value)
Set the callback subroutine name.
Definition ccss.c:1016
void ast_set_cc_agent_dialstring(struct ast_cc_config_params *config, const char *const value)
Set the cc_agent_dialstring.
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:922
void ast_set_cc_max_agents(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_agents.
Definition ccss.c:996
static enum ast_cc_monitor_policies str_to_monitor_policy(const char *const value)
Definition ccss.c:733
void ast_set_ccnr_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccnr_available_timer.
Definition ccss.c:937
static enum ast_cc_agent_policies str_to_agent_policy(const char *const value)
Definition ccss.c:719
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:905
void ast_set_cc_recall_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_recall_timer.
Definition ccss.c:952

References ast_log, 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(), ast_set_ccnr_available_timer(), LOG_WARNING, name, str_to_agent_policy(), str_to_monitor_policy(), and value.

Referenced by acf_cc_write(), and process_dahdi().

◆ ast_get_cc_agent_dialstring()

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

978{
979 return config->cc_agent_dialstring;
980}
static const char config[]

References config.

Referenced by ast_cc_get_param(), and generic_recall().

◆ ast_get_cc_agent_policy()

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

884{
885 return config->cc_agent_policy;
886}

References ast_cc_config_params::cc_agent_policy, and config.

Referenced by ast_cc_call_init(), ast_cc_get_param(), cc_core_init_instance(), and find_agent_callbacks().

◆ ast_get_cc_callback_sub()

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

1012{
1013 return config->cc_callback_sub;
1014}

References config.

Referenced by ast_cc_get_param(), and generic_recall().

◆ ast_get_cc_max_agents()

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

992{
993 return config->cc_max_agents;
994}

References config.

Referenced by ast_cc_get_param(), and cc_core_init_instance().

◆ ast_get_cc_max_monitors()

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

1002{
1003 return config->cc_max_monitors;
1004}

References config.

Referenced by ast_cc_get_param(), and ast_queue_cc_frame().

◆ ast_get_cc_monitor_policy()

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

901{
902 return config->cc_monitor_policy;
903}

References config.

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

◆ ast_get_cc_offer_timer()

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

918{
919 return config->cc_offer_timer;
920}

References config.

Referenced by ast_cc_get_param(), and cc_generic_agent_start_offer_timer().

◆ ast_get_cc_recall_timer()

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

948{
949 return config->cc_recall_timer;
950}

References config.

Referenced by ast_cc_get_param(), and generic_recall().

◆ ast_get_ccbs_available_timer()

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

963{
964 return config->ccbs_available_timer;
965}

References config.

Referenced by ast_cc_get_param(), and cc_generic_monitor_request_cc().

◆ ast_get_ccnr_available_timer()

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

933{
934 return config->ccnr_available_timer;
935}

References config.

Referenced by ast_cc_get_param(), and cc_generic_monitor_request_cc().

◆ ast_handle_cc_control_frame()

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

2335{
2336 char *device_name;
2337 char *dialstring;
2338 struct ast_cc_monitor *monitor;
2339 struct ast_datastore *cc_datastore;
2340 struct dialed_cc_interfaces *cc_interfaces;
2341 struct cc_control_payload *cc_data = frame_data;
2342 struct cc_core_instance *core_instance;
2343
2345
2346 device_name = cc_data->device_name;
2347 dialstring = cc_data->dialstring;
2348
2349 ast_channel_lock(inbound);
2350 if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
2351 ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name);
2352 ast_channel_unlock(inbound);
2354 return;
2355 }
2356
2357 cc_interfaces = cc_datastore->data;
2358
2359 if (cc_interfaces->ignore) {
2360 ast_channel_unlock(inbound);
2362 return;
2363 }
2364
2365 if (!cc_interfaces->is_original_caller) {
2366 /* If the is_original_caller is not set on the *inbound* channel, then
2367 * it must be a local channel. As such, we do not want to create a core instance
2368 * or an agent for the local channel. Instead, we want to pass this along to the
2369 * other side of the local channel so that the original caller can benefit.
2370 */
2371 ast_channel_unlock(inbound);
2372 ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data));
2373 return;
2374 }
2375
2376 core_instance = find_cc_core_instance(cc_interfaces->core_id);
2377 if (!core_instance) {
2378 core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree,
2379 cc_interfaces->core_id, cc_data);
2380 if (!core_instance) {
2381 cc_interfaces->ignore = 1;
2382 ast_channel_unlock(inbound);
2384 return;
2385 }
2386 }
2387
2388 ast_channel_unlock(inbound);
2389
2390 /* Yeah this kind of sucks, but luckily most people
2391 * aren't dialing thousands of interfaces on every call
2392 *
2393 * This traversal helps us to not create duplicate monitors in
2394 * case a device queues multiple CC control frames.
2395 */
2396 AST_LIST_LOCK(cc_interfaces->interface_tree);
2397 AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) {
2398 if (!strcmp(monitor->interface->device_name, device_name)) {
2399 ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n",
2400 core_instance->core_id, device_name);
2401 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2402 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2404 return;
2405 }
2406 }
2407 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2408
2409 if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) {
2410 ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name);
2411 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2413 return;
2414 }
2415
2416 AST_LIST_LOCK(cc_interfaces->interface_tree);
2417 cc_ref(monitor, "monitor tree's reference to the monitor");
2418 AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next);
2419 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2420
2421 cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0);
2422
2423 cc_publish_available(cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service));
2424
2425 cc_unref(core_instance, "Done with core_instance after handling CC control frame");
2426 cc_unref(monitor, "Unref reference from allocating monitor");
2427}
static void cc_publish_available(int core_id, const char *callee, const char *service)
Definition ccss.c:1065
static struct cc_core_instance * cc_core_init_instance(struct ast_channel *caller_chan, struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data)
Definition ccss.c:2958
static struct ast_cc_monitor * cc_device_monitor_init(const char *const device_name, const char *const dialstring, const struct cc_control_payload *cc_data, int core_id)
Definition ccss.c:2268
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)
Definition ccss.c:2069
static const char * cc_service_to_string(enum ast_cc_service_type service)
Definition ccss.c:428
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:4648
unsigned int parent_id
Definition ccss.h:490
enum ast_cc_service_type service
Service offered by the endpoint.
Definition ccss.c:281

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_CC, ast_indicate_data(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_log_dynamic_level, call_destructor_with_no_monitor(), cc_core_init_instance(), cc_device_monitor_init(), cc_extension_monitor_change_is_valid(), cc_logger_level, cc_publish_available(), cc_ref(), cc_service_to_string(), cc_unref(), cc_core_instance::core_id, dialed_cc_interfaces::core_id, ast_datastore::data, ast_cc_interface::device_name, cc_control_payload::device_name, dialed_cc_interfaces_info, ast_cc_monitor::dialstring, cc_control_payload::dialstring, find_cc_core_instance(), dialed_cc_interfaces::ignore, ast_cc_monitor::interface, dialed_cc_interfaces::interface_tree, dialed_cc_interfaces::is_original_caller, LOG_WARNING, cc_control_payload::monitor_type, NULL, ast_cc_monitor::parent_id, cc_control_payload::private_data, RETURN_IF_NOT_ENABLED, and cc_control_payload::service.

Referenced by ast_cc_busy_interface(), ast_cc_call_failed(), and wait_for_answer().

◆ ast_ignore_cc()

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

3748{
3749 struct ast_datastore *cc_datastore;
3750 struct ast_datastore *cc_recall_datastore;
3751 struct dialed_cc_interfaces *cc_interfaces;
3752 struct cc_recall_ds_data *recall_cc_data;
3753
3755
3756 ast_channel_lock(chan);
3757 if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
3758 cc_interfaces = cc_datastore->data;
3759 cc_interfaces->ignore = 1;
3760 }
3761
3762 if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3763 recall_cc_data = cc_recall_datastore->data;
3764 recall_cc_data->ignore = 1;
3765 }
3766 ast_channel_unlock(chan);
3767}

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore::data, dialed_cc_interfaces_info, dialed_cc_interfaces::ignore, cc_recall_ds_data::ignore, NULL, recall_ds_info, and RETURN_IF_NOT_ENABLED.

Referenced by dial_exec_full(), and do_forward().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 4792 of file ccss.c.

◆ ast_queue_cc_frame()

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

4208{
4209 struct ast_frame frame = {0,};
4210 char device_name[AST_CHANNEL_NAME];
4211 int retval;
4212 struct ast_cc_config_params *cc_params;
4213
4215
4216 cc_params = ast_channel_get_cc_config_params(chan);
4217 if (!cc_params) {
4218 return -1;
4219 }
4220 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4221 if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
4222 ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
4223 return -1;
4224 }
4225
4226 if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) {
4227 /* Frame building failed. We can't use this. */
4228 return -1;
4229 }
4230 retval = ast_queue_frame(chan, &frame);
4231 ast_frfree(&frame);
4232 return retval;
4233}
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:4438
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:4235
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:1170
#define ast_frfree(fr)
#define LOG_NOTICE
Data structure associated with a single frame of data.

References ast_cc_build_frame(), ast_cc_monitor_count(), ast_channel_get_cc_config_params(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_frfree, ast_get_cc_max_monitors(), ast_log, ast_queue_frame(), LOG_NOTICE, RETURN_IF_NOT_ENABLED, and service.

Referenced by analog_call().

◆ ast_set_cc_agent_dialstring()

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

983{
984 if (ast_strlen_zero(value)) {
985 config->cc_agent_dialstring[0] = '\0';
986 } else {
987 ast_copy_string(config->cc_agent_dialstring, value, sizeof(config->cc_agent_dialstring));
988 }
989}

References ast_copy_string(), ast_strlen_zero(), config, and value.

Referenced by ast_cc_set_param().

◆ ast_set_cc_agent_policy()

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

889{
890 /* Screw C and its weak type checking for making me have to do this
891 * validation at runtime.
892 */
893 if (value < AST_CC_AGENT_NEVER || value > AST_CC_AGENT_GENERIC) {
894 return -1;
895 }
896 config->cc_agent_policy = value;
897 return 0;
898}

References AST_CC_AGENT_GENERIC, config, and value.

Referenced by ast_cc_set_param().

◆ ast_set_cc_callback_sub()

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

1017{
1018 if (ast_strlen_zero(value)) {
1019 config->cc_callback_sub[0] = '\0';
1020 } else {
1021 ast_copy_string(config->cc_callback_sub, value, sizeof(config->cc_callback_sub));
1022 }
1023}

References ast_copy_string(), ast_strlen_zero(), config, and value.

Referenced by ast_cc_set_param().

◆ ast_set_cc_interfaces_chanvar()

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

3694{
3695 struct ast_datastore *recall_datastore;
3696 struct cc_monitor_tree *interface_tree;
3697 struct ast_cc_monitor *monitor_iter;
3698 struct cc_recall_ds_data *recall_data;
3699 struct ast_str *str = ast_str_create(64);
3700 int core_id;
3701
3703
3704 if (!str) {
3705 return -1;
3706 }
3707
3708 ast_channel_lock(chan);
3709 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3710 ast_channel_unlock(chan);
3711 ast_free(str);
3712 return -1;
3713 }
3714 recall_data = recall_datastore->data;
3715 interface_tree = recall_data->interface_tree;
3716 core_id = recall_data->core_id;
3717 ast_channel_unlock(chan);
3718
3719 AST_LIST_LOCK(interface_tree);
3720 AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) {
3721 if (!strcmp(monitor_iter->interface->device_name, extension)) {
3722 break;
3723 }
3724 }
3725
3726 if (!monitor_iter) {
3727 /* We couldn't find this extension. This may be because
3728 * we have been directed into an unexpected extension because
3729 * the admin has changed a CC_INTERFACES variable at some point.
3730 */
3731 AST_LIST_UNLOCK(interface_tree);
3732 ast_free(str);
3733 return -1;
3734 }
3735
3736 build_cc_interfaces_chanvar(monitor_iter, &str);
3737 AST_LIST_UNLOCK(interface_tree);
3738
3739 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3740 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3741 core_id, ast_str_buffer(str));
3742
3743 ast_free(str);
3744 return 0;
3745}
structure to hold extensions

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_str_buffer(), ast_str_create, build_cc_interfaces_chanvar(), cc_logger_level, cc_recall_ds_data::core_id, ast_datastore::data, ast_cc_interface::device_name, ast_cc_monitor::interface, cc_recall_ds_data::interface_tree, NULL, pbx_builtin_setvar_helper(), recall_ds_info, RETURN_IF_NOT_ENABLED, and str.

Referenced by local_call().

◆ ast_set_cc_max_agents()

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

997{
998 config->cc_max_agents = value;
999}

References config, and value.

Referenced by ast_cc_set_param().

◆ ast_set_cc_max_monitors()

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

1007{
1008 config->cc_max_monitors = value;
1009}

References config, and value.

Referenced by ast_cc_set_param().

◆ ast_set_cc_monitor_policy()

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

906{
907 /* Screw C and its weak type checking for making me have to do this
908 * validation at runtime.
909 */
910 if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) {
911 return -1;
912 }
913 config->cc_monitor_policy = value;
914 return 0;
915}
@ AST_CC_MONITOR_ALWAYS
Definition ccss.h:87

References AST_CC_MONITOR_ALWAYS, config, and value.

Referenced by ast_cc_set_param().

◆ ast_set_cc_offer_timer()

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

923{
924 /* 0 is an unreasonable value for any timer. Stick with the default */
925 if (value == 0) {
926 ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer);
927 return;
928 }
929 config->cc_offer_timer = value;
930}

References ast_log, config, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

◆ ast_set_cc_recall_timer()

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

953{
954 /* 0 is an unreasonable value for any timer. Stick with the default */
955 if (value == 0) {
956 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->cc_recall_timer);
957 return;
958 }
959 config->cc_recall_timer = value;
960}

References ast_log, config, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

◆ ast_set_ccbs_available_timer()

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

968{
969 /* 0 is an unreasonable value for any timer. Stick with the default */
970 if (value == 0) {
971 ast_log(LOG_WARNING, "0 is an invalid value for ccbs_available_timer. Retaining value as %u\n", config->ccbs_available_timer);
972 return;
973 }
974 config->ccbs_available_timer = value;
975}

References ast_log, config, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

◆ ast_set_ccnr_available_timer()

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

938{
939 /* 0 is an unreasonable value for any timer. Stick with the default */
940 if (value == 0) {
941 ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->ccnr_available_timer);
942 return;
943 }
944 config->ccnr_available_timer = value;
945}

References ast_log, config, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

◆ ast_setup_cc_recall_datastore()

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

3424{
3425 struct ast_datastore *recall_datastore;
3426 struct cc_recall_ds_data *recall_data;
3427 struct cc_core_instance *core_instance;
3428
3430
3431 recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL);
3432 if (!recall_datastore) {
3433 return -1;
3434 }
3435
3436 if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) {
3437 ast_datastore_free(recall_datastore);
3438 return -1;
3439 }
3440
3441 if (!(core_instance = find_cc_core_instance(core_id))) {
3442 ast_free(recall_data);
3443 ast_datastore_free(recall_datastore);
3444 return -1;
3445 }
3446
3447 recall_data->interface_tree = cc_ref(core_instance->monitors,
3448 "Bump refcount for monitor tree for recall datastore");
3449 recall_data->core_id = core_id;
3450 recall_datastore->data = recall_data;
3451 recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
3452 ast_channel_lock(chan);
3453 ast_channel_datastore_add(chan, recall_datastore);
3454 ast_channel_unlock(chan);
3455 cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref");
3456 return 0;
3457}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2375
#define DATASTORE_INHERIT_FOREVER
Definition channel.h:194
#define ast_datastore_alloc(info, uid)
Definition datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition datastore.c:68
unsigned int inheritance
Definition datastore.h:69

References ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_free, cc_ref(), cc_unref(), cc_core_instance::core_id, cc_recall_ds_data::core_id, ast_datastore::data, DATASTORE_INHERIT_FOREVER, find_cc_core_instance(), ast_datastore::inheritance, cc_recall_ds_data::interface_tree, cc_core_instance::monitors, NULL, recall_ds_info, and RETURN_IF_NOT_ENABLED.

Referenced by generic_recall().

◆ build_cc_interfaces_chanvar()

static void build_cc_interfaces_chanvar ( struct ast_cc_monitor starting_point,
struct ast_str **  str 
)
static

Definition at line 3611 of file ccss.c.

3612{
3613 struct extension_monitor_pvt *extension_pvt;
3614 struct extension_child_dialstring *child_dialstring;
3615 struct ast_cc_monitor *monitor_iter = starting_point;
3616 int top_level_id = starting_point->id;
3617 size_t length;
3618
3619 /* Init to an empty string. */
3620 ast_str_truncate(*str, 0);
3621
3622 /* First we need to take all of the is_valid child_dialstrings from
3623 * the extension monitor we found and add them to the CC_INTERFACES
3624 * chanvar
3625 */
3626 extension_pvt = starting_point->private_data;
3627 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
3628 if (child_dialstring->is_valid) {
3629 cc_unique_append(str, child_dialstring->original_dialstring);
3630 }
3631 }
3632
3633 /* And now we get the dialstrings from each of the device monitors */
3634 while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) {
3635 if (monitor_iter->parent_id == top_level_id) {
3636 cc_unique_append(str, monitor_iter->dialstring);
3637 }
3638 }
3639
3640 /* str will have an extra '&' tacked onto the end of it, so we need
3641 * to get rid of that.
3642 */
3643 length = ast_str_strlen(*str);
3644 if (length) {
3645 ast_str_truncate(*str, length - 1);
3646 }
3647 if (length <= 1) {
3648 /* Nothing to recall? This should not happen. */
3649 ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n",
3650 starting_point->interface->device_name);
3651 }
3652}
static void cc_unique_append(struct ast_str **str, const char *dialstring)
Definition ccss.c:3582
#define LOG_ERROR
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition strings.h:786
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition strings.h:730
char * dialstring
Name that should be used to recall specified interface.
Definition ccss.h:509

References AST_LIST_NEXT, AST_LIST_TRAVERSE, ast_log, ast_str_strlen(), ast_str_truncate(), cc_unique_append(), extension_monitor_pvt::child_dialstrings, ast_cc_interface::device_name, ast_cc_monitor::dialstring, ast_cc_monitor::id, ast_cc_monitor::interface, extension_child_dialstring::is_valid, LOG_ERROR, ast_cc_monitor::next, extension_child_dialstring::original_dialstring, ast_cc_monitor::parent_id, ast_cc_monitor::private_data, and str.

Referenced by ast_cc_agent_set_interfaces_chanvar(), and ast_set_cc_interfaces_chanvar().

◆ call_destructor_with_no_monitor()

static void call_destructor_with_no_monitor ( const char *const  monitor_type,
void *  private_data 
)
static

Definition at line 2233 of file ccss.c.

2234{
2235 const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type);
2236
2237 if (!monitor_callbacks) {
2238 return;
2239 }
2240
2241 monitor_callbacks->destructor(private_data);
2242}
static const struct ast_cc_monitor_callbacks * find_monitor_callbacks(const char *const type)
Definition ccss.c:1205
Callbacks defined by CC monitors.
Definition ccss.h:542
void(* destructor)(void *private_data)
Destroy private data on the monitor.
Definition ccss.h:634

References ast_cc_monitor_callbacks::destructor, and find_monitor_callbacks().

Referenced by ast_cc_busy_interface(), and ast_handle_cc_control_frame().

◆ cancel_available_timer()

static void cancel_available_timer ( struct cc_core_instance core_instance)
static

Definition at line 3244 of file ccss.c.

3245{
3246 struct ast_cc_monitor *monitor_iter;
3247 AST_LIST_LOCK(core_instance->monitors);
3248 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3249 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3250 if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) {
3252 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3253 monitor_iter->interface->device_name, 1);
3254 cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor");
3255 }
3256 }
3257 }
3259
3260 if (!has_device_monitors(core_instance)) {
3261 ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers");
3262 }
3263 AST_LIST_UNLOCK(core_instance->monitors);
3264}
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition ccss.c:3111
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition ccss.c:3924
@ AST_CC_DEVICE_MONITOR
Definition ccss.h:463
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
enum ast_cc_monitor_class monitor_class
Definition ccss.h:784
int(* cancel_available_timer)(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
Definition ccss.h:623
const struct ast_cc_monitor_callbacks * callbacks
Definition ccss.h:517

References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, ast_cc_interface::device_name, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, ast_cc_monitor::next, and ast_cc_monitor::parent_id.

Referenced by cc_recalling().

◆ cc_active()

static int cc_active ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3186 of file ccss.c.

3187{
3188 /* Either
3189 * 1. Callee accepted CC request, call agent's ack callback.
3190 * 2. Caller became available, call agent's stop_monitoring callback and
3191 * call monitor's unsuspend callback.
3192 */
3193 if (previous_state == CC_CALLER_REQUESTED) {
3194 core_instance->agent->callbacks->respond(core_instance->agent,
3196 cc_publish_requestacknowledged(core_instance->core_id, core_instance->agent->device_name);
3197 } else if (previous_state == CC_CALLER_BUSY) {
3198 cc_publish_callerstopmonitoring(core_instance->core_id, core_instance->agent->device_name);
3199 unsuspend(core_instance);
3200 }
3201 /* Not possible for previous_state to be anything else due to the is_state_change_valid check at the beginning */
3202 return 0;
3203}
static void cc_publish_requestacknowledged(int core_id, const char *caller)
Definition ccss.c:1101
static void unsuspend(struct cc_core_instance *core_instance)
Definition ccss.c:3164
static void cc_publish_callerstopmonitoring(int core_id, const char *caller)
Definition ccss.c:1112
@ AST_CC_AGENT_RESPONSE_SUCCESS
Definition ccss.h:843
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition ccss.h:928
char device_name[1]
Definition ccss.h:838

References cc_core_instance::agent, AST_CC_AGENT_RESPONSE_SUCCESS, ast_cc_agent::callbacks, CC_CALLER_BUSY, CC_CALLER_REQUESTED, cc_publish_callerstopmonitoring(), cc_publish_requestacknowledged(), cc_core_instance::core_id, ast_cc_agent::device_name, ast_cc_agent_callbacks::respond, and unsuspend().

◆ cc_agent_callback_helper()

static int cc_agent_callback_helper ( void *  obj,
void *  args,
int  flags 
)
static

Definition at line 460 of file ccss.c.

461{
462 struct cc_core_instance *core_instance = obj;
463 struct cc_callback_helper *helper = args;
464
465 if (strcmp(core_instance->agent->callbacks->type, helper->type)) {
466 return 0;
467 }
468
469 return helper->function(core_instance->agent, helper->args, flags);
470}
const char * type
Type of agent the callbacks belong to.
Definition ccss.h:857
const char * type
Definition ccss.c:457

References cc_core_instance::agent, cc_callback_helper::args, args, ast_cc_agent::callbacks, cc_callback_helper::function, ast_cc_agent_callbacks::type, and cc_callback_helper::type.

Referenced by ast_cc_agent_callback().

◆ cc_agent_init()

static struct ast_cc_agent * cc_agent_init ( struct ast_channel caller_chan,
const char *const  caller_name,
const int  core_id,
struct cc_monitor_tree interface_tree 
)
static

Definition at line 2583 of file ccss.c.

2586{
2587 struct ast_cc_agent *agent;
2588 struct ast_cc_config_params *cc_params;
2589
2590 if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy,
2591 "Allocating new ast_cc_agent"))) {
2592 return NULL;
2593 }
2594
2595 agent->core_id = core_id;
2596 strcpy(agent->device_name, caller_name);
2597
2598 cc_params = ast_channel_get_cc_config_params(caller_chan);
2599 if (!cc_params) {
2600 cc_unref(agent, "Could not get channel config params.");
2601 return NULL;
2602 }
2603 if (!(agent->cc_params = ast_cc_config_params_init())) {
2604 cc_unref(agent, "Could not init agent config params.");
2605 return NULL;
2606 }
2607 ast_cc_copy_config_params(agent->cc_params, cc_params);
2608
2609 if (!(agent->callbacks = find_agent_callbacks(caller_chan))) {
2610 cc_unref(agent, "Could not find agent callbacks.");
2611 return NULL;
2612 }
2614
2615 if (agent->callbacks->init(agent, caller_chan)) {
2616 cc_unref(agent, "Agent init callback failed.");
2617 return NULL;
2618 }
2619 ast_log_dynamic_level(cc_logger_level, "Core %u: Created an agent for caller %s\n",
2620 agent->core_id, agent->device_name);
2621 return agent;
2622}
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition astobj2.h:407
static void agent_destroy(void *data)
Definition ccss.c:2573
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
Definition ccss.c:876
static void check_callback_sanity(const struct ast_cc_agent_callbacks *callbacks)
Definition ccss.c:2561
static const struct ast_cc_agent_callbacks * find_agent_callbacks(struct ast_channel *chan)
Definition ccss.c:1283
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition ccss.h:135
int(* init)(struct ast_cc_agent *agent, struct ast_channel *chan)
CC agent initialization.
Definition ccss.h:876
unsigned int core_id
Definition ccss.h:812

References agent_destroy(), ao2_t_alloc, ast_cc_config_params_init, ast_cc_copy_config_params(), ast_channel_get_cc_config_params(), ast_log_dynamic_level, ast_cc_agent::callbacks, cc_logger_level, ast_cc_agent::cc_params, cc_unref(), check_callback_sanity(), ast_cc_agent::core_id, ast_cc_agent::device_name, find_agent_callbacks(), ast_cc_agent_callbacks::init, and NULL.

Referenced by cc_core_init_instance().

◆ cc_available()

static int cc_available ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3075 of file ccss.c.

3076{
3077 /* This should never happen... */
3078 ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n");
3079 return -1;
3080}

References ast_log, and LOG_WARNING.

◆ cc_build_payload()

static int cc_build_payload ( struct ast_channel chan,
struct ast_cc_config_params cc_params,
const char *  monitor_type,
const char *const  device_name,
const char *  dialstring,
enum ast_cc_service_type  service,
void *  private_data,
struct cc_control_payload payload 
)
static

Definition at line 4178 of file ccss.c.

4181{
4182 struct ast_datastore *datastore;
4183 struct dialed_cc_interfaces *cc_interfaces;
4184 int dial_parent_id;
4185
4186 ast_channel_lock(chan);
4188 if (!datastore) {
4189 ast_channel_unlock(chan);
4190 return -1;
4191 }
4192 cc_interfaces = datastore->data;
4193 dial_parent_id = cc_interfaces->dial_parent_id;
4194 ast_channel_unlock(chan);
4195
4196 payload->monitor_type = monitor_type;
4197 payload->private_data = private_data;
4198 payload->service = service;
4199 ast_cc_copy_config_params(&payload->config_params, cc_params);
4201 ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
4202 ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring));
4203 return 0;
4204}
int parent_interface_id
ID of parent extension.
Definition ccss.c:299
struct ast_cc_config_params config_params
Configuration parameters used by this endpoint.
Definition ccss.c:290

References ast_cc_copy_config_params(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), cc_control_payload::config_params, ast_datastore::data, cc_control_payload::device_name, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces_info, cc_control_payload::dialstring, cc_control_payload::monitor_type, NULL, cc_control_payload::parent_interface_id, cc_control_payload::private_data, cc_control_payload::service, and service.

Referenced by ast_cc_build_frame(), ast_cc_busy_interface(), and ast_cc_call_failed().

◆ cc_callee_ready()

static int cc_callee_ready ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3205 of file ccss.c.

3206{
3207 core_instance->agent->callbacks->callee_available(core_instance->agent);
3208 return 0;
3209}
int(* callee_available)(struct ast_cc_agent *agent)
Alert the caller that it is time to try recalling.
Definition ccss.h:1021

References cc_core_instance::agent, ast_cc_agent::callbacks, and ast_cc_agent_callbacks::callee_available.

◆ cc_caller_busy()

static int cc_caller_busy ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3233 of file ccss.c.

3234{
3235 /* Callee was available, but caller was busy, call agent's begin_monitoring callback
3236 * and call monitor's suspend callback.
3237 */
3238 suspend(core_instance);
3239 core_instance->agent->callbacks->start_monitoring(core_instance->agent);
3240 cc_publish_callerstartmonitoring(core_instance->core_id, core_instance->agent->device_name);
3241 return 0;
3242}
static void cc_publish_callerstartmonitoring(int core_id, const char *caller)
Definition ccss.c:1123
static void suspend(struct cc_core_instance *core_instance)
Definition ccss.c:3211
int(* start_monitoring)(struct ast_cc_agent *agent)
Begin monitoring a busy device.
Definition ccss.h:1002

References cc_core_instance::agent, ast_cc_agent::callbacks, cc_publish_callerstartmonitoring(), cc_core_instance::core_id, ast_cc_agent::device_name, ast_cc_agent_callbacks::start_monitoring, and suspend().

◆ cc_caller_offered()

static int cc_caller_offered ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3082 of file ccss.c.

3083{
3084 if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) {
3085 ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n",
3086 core_instance->agent->device_name);
3087 return -1;
3088 }
3089 cc_publish_offertimerstart(core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer);
3090 ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n",
3091 core_instance->core_id, core_instance->agent->device_name);
3092 return 0;
3093}
static void cc_publish_offertimerstart(int core_id, const char *caller, unsigned int expires)
Definition ccss.c:1077
int(* start_offer_timer)(struct ast_cc_agent *agent)
Start the offer timer.
Definition ccss.h:897
unsigned int cc_offer_timer
Definition ccss.c:180

References cc_core_instance::agent, ast_cc_failed(), ast_log_dynamic_level, ast_cc_agent::callbacks, cc_logger_level, ast_cc_config_params::cc_offer_timer, ast_cc_agent::cc_params, cc_publish_offertimerstart(), cc_core_instance::core_id, ast_cc_agent::device_name, and ast_cc_agent_callbacks::start_offer_timer.

◆ cc_caller_requested()

static int cc_caller_requested ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3150 of file ccss.c.

3151{
3153 ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n");
3154 core_instance->agent->callbacks->respond(core_instance->agent,
3156 ast_cc_failed(core_instance->core_id, "Too many requests in the system");
3157 return -1;
3158 }
3159 core_instance->agent->callbacks->stop_offer_timer(core_instance->agent);
3160 request_cc(core_instance);
3161 return 0;
3162}
static void request_cc(struct cc_core_instance *core_instance)
Definition ccss.c:3126
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...
Definition ccss.c:2509
@ AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY
Definition ccss.h:847
int(* stop_offer_timer)(struct ast_cc_agent *agent)
Stop the offer timer.
Definition ccss.h:910

References cc_core_instance::agent, AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY, ast_cc_failed(), ast_cc_request_is_within_limits(), ast_log, ast_cc_agent::callbacks, cc_core_instance::core_id, LOG_WARNING, request_cc(), ast_cc_agent_callbacks::respond, and ast_cc_agent_callbacks::stop_offer_timer.

◆ cc_cli_output_status()

static int cc_cli_output_status ( void *  data)
static

Definition at line 4578 of file ccss.c.

4579{
4580 int *cli_fd = data;
4582
4583 if (!count) {
4584 ast_cli(*cli_fd, "There are currently no active call completion transactions\n");
4585 } else {
4586 ast_cli(*cli_fd, "%d Call completion transactions\n", count);
4587 ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n");
4588 ast_cli(*cli_fd, "----------------------------------------------------------------------------\n");
4589 ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI");
4590 }
4591 ast_free(cli_fd);
4592 return 0;
4593}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
static int print_stats_cb(void *obj, void *arg, int flags)
Definition ccss.c:4565
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6

References ao2_container_count(), ao2_t_callback, ast_cli(), ast_free, cc_core_instances, OBJ_NODATA, and print_stats_cb().

Referenced by handle_cc_status().

◆ cc_cli_print_monitor_stats()

static void cc_cli_print_monitor_stats ( struct ast_cc_monitor monitor,
int  fd,
int  parent_id 
)
static

Definition at line 4545 of file ccss.c.

4546{
4547 struct ast_cc_monitor *child_monitor_iter = monitor;
4548 if (!monitor) {
4549 return;
4550 }
4551
4552 ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name);
4554 ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered));
4555 }
4556 ast_cli(fd, "\n");
4557
4558 while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) {
4559 if (child_monitor_iter->parent_id == monitor->id) {
4560 cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id);
4561 }
4562 }
4563}
static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
Definition ccss.c:4545
enum ast_cc_service_type service_offered
Definition ccss.h:498

References AST_CC_DEVICE_MONITOR, ast_cli(), AST_LIST_NEXT, cc_cli_print_monitor_stats(), cc_service_to_string(), ast_cc_interface::device_name, ast_cc_monitor::id, ast_cc_monitor::interface, ast_cc_interface::monitor_class, ast_cc_monitor::next, ast_cc_monitor::parent_id, and ast_cc_monitor::service_offered.

Referenced by cc_cli_print_monitor_stats(), and print_stats_cb().

◆ cc_complete()

static int cc_complete ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3275 of file ccss.c.

3276{
3277 /* Recall has made progress, call agent and monitor destructor functions
3278 */
3279 cc_publish_recallcomplete(core_instance->core_id, core_instance->agent->device_name);
3280 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed");
3281 return 0;
3282}
#define ao2_t_unlink(container, obj, tag)
Definition astobj2.h:1580
static void cc_publish_recallcomplete(int core_id, const char *caller)
Definition ccss.c:1145

References cc_core_instance::agent, ao2_t_unlink, cc_core_instances, cc_publish_recallcomplete(), cc_core_instance::core_id, and ast_cc_agent::device_name.

◆ cc_core_init_instance()

static struct cc_core_instance * cc_core_init_instance ( struct ast_channel caller_chan,
struct cc_monitor_tree called_tree,
const int  core_id,
struct cc_control_payload cc_data 
)
static

Definition at line 2958 of file ccss.c.

2960{
2961 char caller[AST_CHANNEL_NAME];
2962 struct cc_core_instance *core_instance;
2963 struct ast_cc_config_params *cc_params;
2964 long agent_count;
2965 int recall_core_id;
2966
2967 ast_channel_get_device_name(caller_chan, caller, sizeof(caller));
2968 cc_params = ast_channel_get_cc_config_params(caller_chan);
2969 if (!cc_params) {
2970 ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n",
2971 caller);
2972 return NULL;
2973 }
2974 /* First, we need to kill off other pending CC offers from caller. If the caller is going
2975 * to request a CC service, it may only be for the latest call he made.
2976 */
2978 kill_duplicate_offers(caller);
2979 }
2980
2981 ast_cc_is_recall(caller_chan, &recall_core_id, NULL);
2982 agent_count = count_agents(caller, recall_core_id);
2983 if (agent_count >= ast_get_cc_max_agents(cc_params)) {
2984 ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller);
2985 return NULL;
2986 }
2987
2988 /* Generic agents can only have a single outstanding CC request per caller. */
2989 if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
2990 ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n");
2991 return NULL;
2992 }
2993
2994 /* Next, we need to create the core instance for this call */
2995 if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) {
2996 return NULL;
2997 }
2998
2999 core_instance->core_id = core_id;
3000 if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) {
3001 cc_unref(core_instance, "Couldn't allocate agent, unref core_instance");
3002 return NULL;
3003 }
3004
3005 core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree");
3006
3007 ao2_t_link(cc_core_instances, core_instance, "Link core instance into container");
3008
3009 return core_instance;
3010}
#define ao2_t_link(container, obj, tag)
Definition astobj2.h:1534
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.
Definition ccss.c:3459
static void kill_duplicate_offers(char *caller)
Definition ccss.c:2544
static void cc_core_instance_destructor(void *data)
Definition ccss.c:2946
static struct ast_cc_agent * cc_agent_init(struct ast_channel *caller_chan, const char *const caller_name, const int core_id, struct cc_monitor_tree *interface_tree)
Definition ccss.c:2583
static long count_agents(const char *const caller, const int core_id_exception)
Definition ccss.c:2535

References cc_core_instance::agent, ao2_t_alloc, ao2_t_link, AST_CC_AGENT_GENERIC, ast_cc_is_recall(), ast_channel_get_cc_config_params(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_get_cc_agent_policy(), ast_get_cc_max_agents(), ast_log_dynamic_level, cc_agent_init(), cc_core_instance_destructor(), cc_core_instances, cc_logger_level, cc_ref(), cc_unref(), cc_core_instance::core_id, count_agents(), kill_duplicate_offers(), cc_core_instance::monitors, and NULL.

Referenced by ast_handle_cc_control_frame().

◆ cc_core_instance_cmp_fn()

static int cc_core_instance_cmp_fn ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 439 of file ccss.c.

440{
441 struct cc_core_instance *core_instance1 = obj;
442 struct cc_core_instance *core_instance2 = arg;
443
444 return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0;
445}
@ CMP_MATCH
Definition astobj2.h:1027
@ CMP_STOP
Definition astobj2.h:1028

References CMP_MATCH, CMP_STOP, and cc_core_instance::core_id.

Referenced by load_module().

◆ cc_core_instance_destructor()

static void cc_core_instance_destructor ( void *  data)
static

Definition at line 2946 of file ccss.c.

2947{
2948 struct cc_core_instance *core_instance = data;
2949 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id);
2950 if (core_instance->agent) {
2951 cc_unref(core_instance->agent, "Core instance is done with the agent now");
2952 }
2953 if (core_instance->monitors) {
2954 core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list");
2955 }
2956}

References cc_core_instance::agent, ast_log_dynamic_level, cc_logger_level, cc_unref(), cc_core_instance::core_id, and cc_core_instance::monitors.

Referenced by cc_core_init_instance().

◆ cc_core_instance_hash_fn()

static int cc_core_instance_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 433 of file ccss.c.

434{
435 const struct cc_core_instance *core_instance = obj;
436 return core_instance->core_id;
437}

References cc_core_instance::core_id.

Referenced by load_module().

◆ cc_device_monitor_init()

static struct ast_cc_monitor * cc_device_monitor_init ( const char *const  device_name,
const char *const  dialstring,
const struct cc_control_payload cc_data,
int  core_id 
)
static

Definition at line 2268 of file ccss.c.

2269{
2270 struct ast_cc_interface *cc_interface;
2271 struct ast_cc_monitor *monitor;
2272 size_t device_name_len = strlen(device_name);
2273 int parent_id = cc_data->parent_interface_id;
2274
2275 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy,
2276 "Allocating new ast_cc_interface"))) {
2277 return NULL;
2278 }
2279
2280 if (!(cc_interface->config_params = ast_cc_config_params_init())) {
2281 cc_unref(cc_interface, "Failed to allocate config params, unref interface");
2282 return NULL;
2283 }
2284
2285 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
2286 cc_unref(cc_interface, "Failed to allocate monitor, unref interface");
2287 return NULL;
2288 }
2289
2290 if (!(monitor->dialstring = ast_strdup(dialstring))) {
2291 cc_unref(monitor, "Failed to copy dialable name. Unref monitor");
2292 cc_unref(cc_interface, "Failed to copy dialable name");
2293 return NULL;
2294 }
2295
2296 if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) {
2297 cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor");
2298 cc_unref(cc_interface, "Failed to find monitor callbacks");
2299 return NULL;
2300 }
2301
2302 strcpy(cc_interface->device_name, device_name);
2304 monitor->parent_id = parent_id;
2305 monitor->core_id = core_id;
2306 monitor->service_offered = cc_data->service;
2307 monitor->private_data = cc_data->private_data;
2308 cc_interface->monitor_type = cc_data->monitor_type;
2309 cc_interface->monitor_class = AST_CC_DEVICE_MONITOR;
2310 monitor->interface = cc_interface;
2311 monitor->available_timer_id = -1;
2312 ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params);
2313 ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %u and parent %u\n",
2314 monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id);
2315 return monitor;
2316}
static int dialed_cc_interface_counter
Definition ccss.c:1892
static void cc_interface_destroy(void *data)
Definition ccss.c:1754
static void cc_monitor_destroy(void *data)
Definition ccss.c:1854
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition lock.h:764
Structure with information about an outbound interface.
Definition ccss.h:781
struct ast_cc_config_params * config_params
Definition ccss.h:797

References ao2_t_alloc, ast_atomic_fetchadd_int(), ast_cc_config_params_init, ast_cc_copy_config_params(), AST_CC_DEVICE_MONITOR, ast_log_dynamic_level, ast_strdup, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, cc_interface_destroy(), cc_logger_level, cc_monitor_destroy(), cc_unref(), ast_cc_interface::config_params, cc_control_payload::config_params, ast_cc_monitor::core_id, ast_cc_interface::device_name, dialed_cc_interface_counter, ast_cc_monitor::dialstring, find_monitor_callbacks(), ast_cc_monitor::id, ast_cc_monitor::interface, ast_cc_interface::monitor_class, ast_cc_interface::monitor_type, cc_control_payload::monitor_type, NULL, ast_cc_monitor::parent_id, cc_control_payload::parent_interface_id, ast_cc_monitor::private_data, cc_control_payload::private_data, cc_control_payload::service, and ast_cc_monitor::service_offered.

Referenced by ast_handle_cc_control_frame().

◆ cc_do_state_change()

static int cc_do_state_change ( void *  datap)
static

Definition at line 3303 of file ccss.c.

3304{
3305 struct cc_state_change_args *args = datap;
3306 struct cc_core_instance *core_instance;
3307 enum cc_state previous_state;
3308 int res;
3309
3310 ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %u requested. Reason: %s\n",
3311 args->core_id, args->state, args->debug);
3312
3313 core_instance = args->core_instance;
3314
3315 if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) {
3316 ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n",
3317 args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state));
3318 if (args->state == CC_CALLER_REQUESTED) {
3319 /*
3320 * For out-of-order requests, we need to let the requester know that
3321 * we can't handle the request now.
3322 */
3323 core_instance->agent->callbacks->respond(core_instance->agent,
3325 }
3326 ast_free(args);
3327 cc_unref(core_instance, "Unref core instance from when it was found earlier");
3328 return -1;
3329 }
3330
3331 /* We can change to the new state now. */
3332 previous_state = core_instance->current_state;
3333 core_instance->current_state = args->state;
3334 res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state);
3335
3336 /* If state change successful then notify any device state watchers of the change */
3337 if (!res && !strcmp(core_instance->agent->callbacks->type, "generic")) {
3338 ccss_notify_device_state_change(core_instance->agent->device_name, core_instance->current_state);
3339 }
3340
3341 ast_free(args);
3342 cc_unref(core_instance, "Unref since state change has completed"); /* From ao2_find */
3343 return res;
3344}
static int(*const state_change_funcs[])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state)
Definition ccss.c:3291
static void ccss_notify_device_state_change(const char *device, enum cc_state state)
Definition ccss.c:660
cc_state
The states used in the CCSS core state machine.
Definition ccss.c:196
static const char * cc_state_to_string(enum cc_state state)
Definition ccss.c:423
static int is_state_change_valid(enum cc_state current_state, const enum cc_state new_state, struct ast_cc_agent *agent)
Definition ccss.c:3019
@ AST_CC_AGENT_RESPONSE_FAILURE_INVALID
Definition ccss.h:845
enum cc_state current_state
Definition ccss.c:352

References cc_core_instance::agent, args, AST_CC_AGENT_RESPONSE_FAILURE_INVALID, ast_free, ast_log_dynamic_level, ast_cc_agent::callbacks, CC_CALLER_REQUESTED, cc_logger_level, cc_state_to_string(), cc_unref(), ccss_notify_device_state_change(), cc_core_instance::current_state, ast_cc_agent::device_name, is_state_change_valid(), ast_cc_agent_callbacks::respond, state_change_funcs, and ast_cc_agent_callbacks::type.

Referenced by cc_request_state_change().

◆ cc_extension_monitor_change_is_valid()

static void cc_extension_monitor_change_is_valid ( struct cc_core_instance core_instance,
unsigned int  parent_id,
const char *const  device_name,
int  is_valid 
)
static

Definition at line 2069 of file ccss.c.

2070{
2071 struct ast_cc_monitor *monitor_iter;
2072 struct extension_monitor_pvt *extension_pvt;
2073 struct extension_child_dialstring *child_dialstring;
2074
2075 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
2076 if (monitor_iter->id == parent_id) {
2077 break;
2078 }
2079 }
2080
2081 if (!monitor_iter) {
2082 return;
2083 }
2084 extension_pvt = monitor_iter->private_data;
2085
2086 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
2087 if (!strcmp(child_dialstring->device_name, device_name)) {
2088 child_dialstring->is_valid = is_valid;
2089 break;
2090 }
2091 }
2092}
struct extension_child_dialstring * next
Definition ccss.c:1828

References AST_LIST_TRAVERSE, extension_monitor_pvt::child_dialstrings, extension_child_dialstring::device_name, ast_cc_monitor::id, extension_child_dialstring::is_valid, cc_core_instance::monitors, extension_child_dialstring::next, and ast_cc_monitor::private_data.

Referenced by ast_handle_cc_control_frame(), cancel_available_timer(), cc_monitor_failed(), request_cc(), suspend(), and unsuspend().

◆ cc_extension_monitor_destructor()

static void cc_extension_monitor_destructor ( void *  private_data)
static

Definition at line 1838 of file ccss.c.

1839{
1840 struct extension_monitor_pvt *extension_pvt = private_data;
1841 struct extension_child_dialstring *child_dialstring;
1842
1843 /* This shouldn't be possible, but I'm paranoid */
1844 if (!extension_pvt) {
1845 return;
1846 }
1847
1848 while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) {
1849 ast_free(child_dialstring);
1850 }
1851 ast_free(extension_pvt);
1852}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.

References ast_free, AST_LIST_REMOVE_HEAD, extension_monitor_pvt::child_dialstrings, and extension_child_dialstring::next.

Referenced by cc_monitor_destroy().

◆ cc_extension_monitor_init()

static struct ast_cc_monitor * cc_extension_monitor_init ( const char *const  exten,
const char *const  context,
const unsigned int  parent_id 
)
static

Definition at line 2108 of file ccss.c.

2109{
2111 struct ast_cc_interface *cc_interface;
2112 struct ast_cc_monitor *monitor;
2113
2114 ast_str_set(&str, 0, "%s@%s", exten, context);
2115
2116 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy,
2117 "Allocating new ast_cc_interface"))) {
2118 return NULL;
2119 }
2120
2121 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
2122 cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface");
2123 return NULL;
2124 }
2125
2126 if (!(monitor->private_data = extension_monitor_pvt_init())) {
2127 cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor");
2128 cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface");
2129 }
2130
2132 monitor->parent_id = parent_id;
2133 cc_interface->monitor_type = "extension";
2135 strcpy(cc_interface->device_name, ast_str_buffer(str));
2136 monitor->interface = cc_interface;
2137 ast_log_dynamic_level(cc_logger_level, "Created an extension cc interface for '%s' with id %u and parent %u\n", cc_interface->device_name, monitor->id, monitor->parent_id);
2138 return monitor;
2139}
static struct extension_monitor_pvt * extension_monitor_pvt_init(void)
Definition ccss.c:2012
@ AST_CC_EXTENSION_MONITOR
Definition ccss.h:464
#define AST_MAX_EXTENSION
Definition channel.h:134
#define ast_str_alloca(init_len)
Definition strings.h:848
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113

References ao2_t_alloc, ast_atomic_fetchadd_int(), AST_CC_EXTENSION_MONITOR, ast_log_dynamic_level, AST_MAX_EXTENSION, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_str_strlen(), cc_interface_destroy(), cc_logger_level, cc_monitor_destroy(), cc_unref(), ast_cc_interface::device_name, dialed_cc_interface_counter, extension_monitor_pvt_init(), ast_cc_monitor::id, ast_cc_monitor::interface, ast_cc_interface::monitor_class, ast_cc_interface::monitor_type, NULL, ast_cc_monitor::parent_id, ast_cc_monitor::private_data, and str.

Referenced by ast_cc_call_init(), and cc_interfaces_datastore_init().

◆ cc_failed()

static int cc_failed ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3284 of file ccss.c.

3285{
3286 cc_publish_failure(core_instance->core_id, core_instance->agent->device_name, args->debug);
3287 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed");
3288 return 0;
3289}
static void cc_publish_failure(int core_id, const char *caller, const char *reason)
Definition ccss.c:1156

References cc_core_instance::agent, ao2_t_unlink, args, cc_core_instances, cc_publish_failure(), cc_core_instance::core_id, and ast_cc_agent::device_name.

◆ cc_generic_agent_destructor()

static void cc_generic_agent_destructor ( struct ast_cc_agent agent)
static

Definition at line 2929 of file ccss.c.

2930{
2932
2933 if (!agent_pvt) {
2934 /* The agent constructor probably failed. */
2935 return;
2936 }
2937
2939 if (agent_pvt->sub) {
2941 }
2942
2944}
static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
Definition ccss.c:2751
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition stasis.c:1038
Structure representing an agent.
void * private_data
Definition ccss.h:834

References ast_free, cc_generic_agent_stop_offer_timer(), ast_cc_agent::private_data, and stasis_unsubscribe().

◆ cc_generic_agent_init()

static int cc_generic_agent_init ( struct ast_cc_agent agent,
struct ast_channel chan 
)
static

Definition at line 2698 of file ccss.c.

2699{
2700 struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
2701
2702 if (!generic_pvt) {
2703 return -1;
2704 }
2705
2706 generic_pvt->offer_timer_id = -1;
2707 if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
2708 ast_copy_string(generic_pvt->cid_num, ast_channel_caller(chan)->id.number.str, sizeof(generic_pvt->cid_num));
2709 }
2710 if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
2711 ast_copy_string(generic_pvt->cid_name, ast_channel_caller(chan)->id.name.str, sizeof(generic_pvt->cid_name));
2712 }
2713 ast_copy_string(generic_pvt->exten, ast_channel_exten(chan), sizeof(generic_pvt->exten));
2714 ast_copy_string(generic_pvt->context, ast_channel_context(chan), sizeof(generic_pvt->context));
2715 agent->private_data = generic_pvt;
2717 return 0;
2718}
@ AST_CC_AGENT_SKIP_OFFER
Definition ccss.h:67
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
char context[AST_CHANNEL_NAME]
Definition ccss.c:2695
char cid_num[AST_CHANNEL_NAME]
Definition ccss.c:2671
char cid_name[AST_CHANNEL_NAME]
Definition ccss.c:2679
char exten[AST_CHANNEL_NAME]
Definition ccss.c:2687
Number structure.
#define ast_set_flag(p, flag)
Definition utils.h:71

References ast_calloc, AST_CC_AGENT_SKIP_OFFER, ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_copy_string(), ast_set_flag, cc_generic_agent_pvt::cid_name, cc_generic_agent_pvt::cid_num, cc_generic_agent_pvt::context, cc_generic_agent_pvt::exten, name, cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.

◆ cc_generic_agent_recall()

static int cc_generic_agent_recall ( struct ast_cc_agent agent)
static

Definition at line 2913 of file ccss.c.

2914{
2915 pthread_t clotho;
2916 enum ast_device_state current_state = ast_device_state(agent->device_name);
2917
2918 if (!cc_generic_is_device_available(current_state)) {
2919 /* We can't try to contact the device right now because he's not available
2920 * Let the core know he's busy.
2921 */
2922 ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name);
2923 return 0;
2924 }
2926 return 0;
2927}
int ast_cc_agent_caller_busy(int core_id, const char *debug,...)
Indicate that the caller is busy.
Definition ccss.c:3846
static int cc_generic_is_device_available(enum ast_device_state state)
Definition ccss.c:1327
static void * generic_recall(void *data)
Definition ccss.c:2845
ast_device_state
Device States.
Definition devicestate.h:52
#define ast_pthread_create_detached_background(a, b, c, d)
Definition utils.h:637

References ast_cc_agent_caller_busy(), ast_pthread_create_detached_background, cc_generic_is_device_available(), ast_cc_agent::core_id, ast_cc_agent::device_name, generic_recall(), and NULL.

◆ cc_generic_agent_respond()

static void cc_generic_agent_respond ( struct ast_cc_agent agent,
enum ast_cc_agent_response_reason  reason 
)
static

Definition at line 2764 of file ccss.c.

2765{
2766 /* The generic agent doesn't have to do anything special to
2767 * acknowledge a CC request. Just return.
2768 */
2769 return;
2770}

◆ cc_generic_agent_start_monitoring()

static int cc_generic_agent_start_monitoring ( struct ast_cc_agent agent)
static

Definition at line 2820 of file ccss.c.

2821{
2822 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2823 struct ast_str *str = ast_str_alloca(128);
2824 struct stasis_topic *device_specific_topic;
2825
2826 ast_assert(generic_pvt->sub == NULL);
2827 ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n",
2828 agent->device_name);
2829
2830 device_specific_topic = ast_device_state_topic(agent->device_name);
2831 if (!device_specific_topic) {
2832 return -1;
2833 }
2834
2835 if (!(generic_pvt->sub = stasis_subscribe(device_specific_topic, generic_agent_devstate_cb, agent))) {
2836 return -1;
2837 }
2841 cc_ref(agent, "Ref agent for subscription");
2842 return 0;
2843}
static void generic_agent_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Definition ccss.c:2790
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition stasis.c:1090
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition stasis.c:1144
#define stasis_subscribe(topic, callback, data)
Definition stasis.h:649
struct stasis_subscription * sub
Definition ccss.c:2657

References ast_assert, ast_device_state_message_type(), ast_device_state_topic(), ast_str_alloca, ast_str_set(), cc_ref(), ast_cc_agent::device_name, generic_agent_devstate_cb(), NULL, ast_cc_agent::private_data, stasis_subscribe, stasis_subscription_accept_message_type(), stasis_subscription_change_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), str, and cc_generic_agent_pvt::sub.

◆ cc_generic_agent_start_offer_timer()

static int cc_generic_agent_start_offer_timer ( struct ast_cc_agent agent)
static

Definition at line 2732 of file ccss.c.

2733{
2734 int when;
2735 int sched_id;
2736 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2737
2739 ast_assert(agent->cc_params != NULL);
2740
2741 when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
2742 ast_log_dynamic_level(cc_logger_level, "Core %u: About to schedule offer timer expiration for %d ms\n",
2743 agent->core_id, when);
2744 if ((sched_id = ast_sched_add(cc_sched_context, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) {
2745 return -1;
2746 }
2747 generic_pvt->offer_timer_id = sched_id;
2748 return 0;
2749}
static struct ast_sched_context * cc_sched_context
Definition ccss.c:131
static int offer_timer_expire(const void *data)
Definition ccss.c:2720
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition sched.c:567
Scheduler ID holder.
Definition sched.c:70

References ast_assert, ast_get_cc_offer_timer(), ast_log_dynamic_level, ast_sched_add(), cc_logger_level, ast_cc_agent::cc_params, cc_ref(), cc_sched_context, ast_cc_agent::core_id, NULL, offer_timer_expire(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.

◆ cc_generic_agent_status_request()

static int cc_generic_agent_status_request ( struct ast_cc_agent agent)
static

Definition at line 2772 of file ccss.c.

2773{
2775 return 0;
2776}
int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate)
Response with a caller's current status.
Definition ccss.c:4148

References ast_cc_agent_status_response(), ast_cc_agent::core_id, and ast_cc_agent::device_name.

◆ cc_generic_agent_stop_offer_timer()

static int cc_generic_agent_stop_offer_timer ( struct ast_cc_agent agent)
static

Definition at line 2751 of file ccss.c.

2752{
2753 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2754
2755 if (generic_pvt->offer_timer_id != -1) {
2756 if (!ast_sched_del(cc_sched_context, generic_pvt->offer_timer_id)) {
2757 cc_unref(agent, "Remove scheduler's reference to the agent");
2758 }
2759 generic_pvt->offer_timer_id = -1;
2760 }
2761 return 0;
2762}
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition sched.c:614

References ast_sched_del(), cc_sched_context, cc_unref(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.

Referenced by cc_generic_agent_destructor().

◆ cc_generic_agent_stop_ringing()

static int cc_generic_agent_stop_ringing ( struct ast_cc_agent agent)
static

Definition at line 2778 of file ccss.c.

2779{
2780 struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name));
2781
2782 if (!recall_chan) {
2783 return 0;
2784 }
2785
2787 return 0;
2788}
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition channel.c:1399
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2461
@ AST_SOFTHANGUP_EXPLICIT
Definition channel.h:1168
Main Channel structure associated with a channel.

References ast_channel_get_by_name_prefix(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, and ast_cc_agent::device_name.

◆ cc_generic_is_device_available()

static int cc_generic_is_device_available ( enum ast_device_state  state)
static

◆ cc_generic_monitor_cancel_available_timer()

static int cc_generic_monitor_cancel_available_timer ( struct ast_cc_monitor monitor,
int *  sched_id 
)
static

Definition at line 1668 of file ccss.c.

1669{
1671
1672 if (*sched_id == -1) {
1673 return 0;
1674 }
1675
1676 ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n",
1677 monitor->core_id, monitor->interface->device_name);
1679 cc_unref(monitor, "Remove scheduler's reference to the monitor");
1680 }
1681 *sched_id = -1;
1682 return 0;
1683}

References ast_assert, ast_log_dynamic_level, ast_sched_del(), cc_logger_level, cc_sched_context, cc_unref(), ast_cc_monitor::core_id, ast_cc_interface::device_name, ast_cc_monitor::interface, and NULL.

◆ cc_generic_monitor_destructor()

static void cc_generic_monitor_destructor ( void *  private_data)
static

Definition at line 1685 of file ccss.c.

1686{
1687 struct generic_monitor_pvt *gen_mon_pvt = private_data;
1688 struct generic_monitor_instance_list *generic_list;
1689 struct generic_monitor_instance *generic_instance;
1690
1691 if (!private_data) {
1692 /* If the private data is NULL, that means that the monitor hasn't even
1693 * been created yet, but that the destructor was called. While this sort
1694 * of behavior is useful for native monitors, with a generic one, there is
1695 * nothing in particular to do.
1696 */
1697 return;
1698 }
1699
1700 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n",
1701 gen_mon_pvt->core_id, gen_mon_pvt->device_name);
1702
1703 if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) {
1704 /* If there's no generic list, that means that the monitor is being destroyed
1705 * before we actually got to request CC. Not a biggie. Same in the situation
1706 * below if the list traversal should complete without finding an entry.
1707 */
1708 ast_free((char *)gen_mon_pvt->device_name);
1709 ast_free(gen_mon_pvt);
1710 return;
1711 }
1712
1713 AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) {
1714 if (generic_instance->core_id == gen_mon_pvt->core_id) {
1716 ast_free(generic_instance);
1717 break;
1718 }
1719 }
1721
1722 if (AST_LIST_EMPTY(&generic_list->list)) {
1723 /* No more monitors with this device name exist. Time to unlink this
1724 * list from the container
1725 */
1726 ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container");
1727 } else {
1728 /* There are still instances for this particular device. The situation
1729 * may be that we were attempting a CC recall and a failure occurred, perhaps
1730 * on the agent side. If a failure happens here and the device being monitored
1731 * is available, then we need to signal on the first unsuspended instance that
1732 * the device is available for recall.
1733 */
1734
1735 /* First things first. We don't even want to consider this action if
1736 * the device in question isn't available right now.
1737 */
1738 if (generic_list->fit_for_recall
1740 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1741 if (!generic_instance->is_suspended && generic_instance->monitoring) {
1742 ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor "
1743 "availability due to other instance's failure.");
1744 break;
1745 }
1746 }
1747 }
1748 }
1749 cc_unref(generic_list, "Done with generic list in generic monitor destructor");
1750 ast_free((char *)gen_mon_pvt->device_name);
1751 ast_free(gen_mon_pvt);
1752}
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.
Definition ccss.c:3833
struct ao2_container * generic_monitors
Definition ccss.c:1347
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition ccss.c:1400
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
enum ast_device_state current_state
Definition ccss.c:1358
struct generic_monitor_instance_list::@346 list
struct generic_monitor_instance * next
Definition ccss.c:1353
private data for generic device monitor
Definition ccss.c:1382
const char * device_name
Definition ccss.c:1387

References ao2_t_unlink, ast_cc_monitor_callee_available(), ast_free, AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log_dynamic_level, cc_generic_is_device_available(), cc_logger_level, cc_unref(), generic_monitor_instance::core_id, generic_monitor_pvt::core_id, generic_monitor_instance_list::current_state, generic_monitor_pvt::device_name, find_generic_monitor_instance_list(), generic_monitor_instance_list::fit_for_recall, generic_monitors, generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, generic_monitor_instance::monitoring, and generic_monitor_instance::next.

◆ cc_generic_monitor_request_cc()

static int cc_generic_monitor_request_cc ( struct ast_cc_monitor monitor,
int *  available_timer_id 
)
static

Definition at line 1536 of file ccss.c.

1537{
1538 struct generic_monitor_instance_list *generic_list;
1539 struct generic_monitor_instance *generic_instance;
1540 struct generic_monitor_pvt *gen_mon_pvt;
1542 int when;
1543
1544 /* First things first. Native channel drivers will have their private data allocated
1545 * at the time that they tell the core that they can offer CC. Generic is quite a bit
1546 * different, and we wait until this point to allocate our private data.
1547 */
1548 if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) {
1549 return -1;
1550 }
1551
1552 if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) {
1553 ast_free(gen_mon_pvt);
1554 return -1;
1555 }
1556
1557 gen_mon_pvt->core_id = monitor->core_id;
1558
1559 monitor->private_data = gen_mon_pvt;
1560
1561 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1562 if (!(generic_list = create_new_generic_list(monitor))) {
1563 return -1;
1564 }
1565 }
1566
1567 if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) {
1568 /* The generic monitor destructor will take care of the appropriate
1569 * deallocations
1570 */
1571 cc_unref(generic_list, "Generic monitor instance failed to allocate");
1572 return -1;
1573 }
1574 generic_instance->core_id = monitor->core_id;
1575 generic_instance->monitoring = 1;
1576 AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next);
1578 ast_get_ccnr_available_timer(monitor->interface->config_params);
1579
1580 *available_timer_id = ast_sched_add(cc_sched_context, when * 1000,
1581 ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference"));
1582 if (*available_timer_id == -1) {
1583 cc_unref(monitor, "Failed to schedule available timer. (monitor)");
1584 cc_unref(generic_list, "Failed to schedule available timer. (generic_list)");
1585 return -1;
1586 }
1587 /* If the new instance was created as CCNR, then that means this device is not currently
1588 * fit for recall even if it previously was.
1589 */
1590 if (service == AST_CC_CCNR || service == AST_CC_CCNL) {
1591 generic_list->fit_for_recall = 0;
1592 }
1593 ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.",
1594 monitor->interface->device_name);
1595 cc_unref(generic_list, "Finished with monitor instance reference in request cc callback");
1596 return 0;
1597}
int ast_cc_available_timer_expire(const void *data)
Scheduler callback for available timer expiration.
Definition ccss.c:1523
int ast_cc_monitor_request_acked(int core_id, const char *const debug,...)
Indicate that an outbound entity has accepted our CC request.
Definition ccss.c:3820
static struct generic_monitor_instance_list * create_new_generic_list(struct ast_cc_monitor *monitor)
Definition ccss.c:1423
ast_cc_service_type
Definition ccss.h:32
@ AST_CC_CCNL
Definition ccss.h:40
@ AST_CC_CCNR
Definition ccss.h:38

References ast_calloc, ast_cc_available_timer_expire(), AST_CC_CCBS, AST_CC_CCNL, AST_CC_CCNR, ast_cc_monitor_request_acked(), ast_free, ast_get_ccbs_available_timer(), ast_get_ccnr_available_timer(), AST_LIST_INSERT_TAIL, ast_sched_add(), ast_strdup, cc_ref(), cc_sched_context, cc_unref(), ast_cc_interface::config_params, ast_cc_monitor::core_id, generic_monitor_instance::core_id, generic_monitor_pvt::core_id, create_new_generic_list(), ast_cc_interface::device_name, generic_monitor_pvt::device_name, find_generic_monitor_instance_list(), generic_monitor_instance_list::fit_for_recall, ast_cc_monitor::interface, generic_monitor_instance_list::list, generic_monitor_instance::monitoring, ast_cc_monitor::private_data, service, and ast_cc_monitor::service_offered.

◆ cc_generic_monitor_suspend()

static int cc_generic_monitor_suspend ( struct ast_cc_monitor monitor)
static

Definition at line 1599 of file ccss.c.

1600{
1601 struct generic_monitor_instance_list *generic_list;
1602 struct generic_monitor_instance *generic_instance;
1604
1605 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1606 return -1;
1607 }
1608
1609 /* First we need to mark this particular monitor as being suspended. */
1610 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1611 if (generic_instance->core_id == monitor->core_id) {
1612 generic_instance->is_suspended = 1;
1613 break;
1614 }
1615 }
1616
1617 /* If the device being suspended is currently in use, then we don't need to
1618 * take any further actions
1619 */
1621 cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list.");
1622 return 0;
1623 }
1624
1625 /* If the device is not in use, though, then it may be possible to report the
1626 * device's availability using a different monitor which is monitoring the
1627 * same device
1628 */
1629
1630 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1631 if (!generic_instance->is_suspended) {
1632 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1633 break;
1634 }
1635 }
1636 cc_unref(generic_list, "Done with generic list in suspend callback");
1637 return 0;
1638}

References ast_cc_monitor_callee_available(), AST_LIST_TRAVERSE, cc_generic_is_device_available(), cc_unref(), ast_cc_monitor::core_id, generic_monitor_instance::core_id, ast_cc_interface::device_name, find_generic_monitor_instance_list(), ast_cc_monitor::interface, generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, and generic_monitor_instance::next.

◆ cc_generic_monitor_unsuspend()

static int cc_generic_monitor_unsuspend ( struct ast_cc_monitor monitor)
static

Definition at line 1640 of file ccss.c.

1641{
1642 struct generic_monitor_instance *generic_instance;
1645
1646 if (!generic_list) {
1647 return -1;
1648 }
1649 /* If the device is currently available, we can immediately announce
1650 * its availability
1651 */
1653 ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available");
1654 }
1655
1656 /* In addition, we need to mark this generic_monitor_instance as not being suspended anymore */
1657 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1658 if (generic_instance->core_id == monitor->core_id) {
1659 generic_instance->is_suspended = 0;
1660 generic_instance->monitoring = 1;
1661 break;
1662 }
1663 }
1664 cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend");
1665 return 0;
1666}

References ast_cc_monitor_callee_available(), AST_LIST_TRAVERSE, cc_generic_is_device_available(), cc_unref(), ast_cc_monitor::core_id, generic_monitor_instance::core_id, ast_cc_interface::device_name, find_generic_monitor_instance_list(), ast_cc_monitor::interface, generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, and generic_monitor_instance::monitoring.

◆ cc_interface_destroy()

static void cc_interface_destroy ( void *  data)
static

Definition at line 1754 of file ccss.c.

1755{
1756 struct ast_cc_interface *interface = data;
1757 ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name);
1758 ast_cc_config_params_destroy(interface->config_params);
1759}

References ast_cc_config_params_destroy(), ast_log_dynamic_level, and cc_logger_level.

Referenced by cc_device_monitor_init(), and cc_extension_monitor_init().

◆ cc_interface_tree_destroy()

static void cc_interface_tree_destroy ( void *  data)
static

Definition at line 1875 of file ccss.c.

1876{
1877 struct cc_monitor_tree *cc_interface_tree = data;
1878 struct ast_cc_monitor *monitor;
1879 while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
1880 if (monitor->callbacks) {
1881 monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id);
1882 }
1883 cc_unref(monitor, "Destroying all monitors");
1884 }
1885 AST_LIST_HEAD_DESTROY(cc_interface_tree);
1886}
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.

References AST_LIST_HEAD_DESTROY, AST_LIST_REMOVE_HEAD, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_unref(), and ast_cc_monitor::next.

Referenced by cc_interfaces_datastore_init().

◆ cc_interfaces_datastore_init()

static int cc_interfaces_datastore_init ( struct ast_channel chan)
static

Definition at line 2157 of file ccss.c.

2157 {
2159 struct ast_cc_monitor *monitor;
2160 struct ast_datastore *dial_cc_datastore;
2161
2162 /*XXX This may be a bit controversial. In an attempt to not allocate
2163 * extra resources, I make sure that a future request will be within
2164 * limits. The problem here is that it is reasonable to think that
2165 * even if we're not within the limits at this point, we may be by
2166 * the time the requestor will have made his request. This may be
2167 * deleted at some point.
2168 */
2170 return 0;
2171 }
2172
2173 if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) {
2174 return -1;
2175 }
2176
2177 if (!(monitor = cc_extension_monitor_init(ast_channel_exten(chan), ast_channel_context(chan), 0))) {
2179 return -1;
2180 }
2181
2182 if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) {
2183 cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor");
2185 return -1;
2186 }
2187
2188 if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy,
2189 "Allocate monitor tree"))) {
2190 ast_datastore_free(dial_cc_datastore);
2191 cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor");
2193 return -1;
2194 }
2195
2196 /* Finally, all that allocation is done... */
2197 AST_LIST_HEAD_INIT(interfaces->interface_tree);
2198 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
2199 cc_ref(monitor, "List's reference to extension monitor");
2200 dial_cc_datastore->data = interfaces;
2201 dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
2202 interfaces->dial_parent_id = monitor->id;
2203 interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1);
2204 interfaces->is_original_caller = 1;
2205 ast_channel_lock(chan);
2206 ast_channel_datastore_add(chan, dial_cc_datastore);
2207 ast_channel_unlock(chan);
2208 cc_unref(monitor, "Unreffing allocation's reference");
2209 return 0;
2210}
static void cc_interface_tree_destroy(void *data)
Definition ccss.c:1875
static int core_id_counter
Definition ccss.c:136
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
struct ast_datastore * next
Definition datastore.h:70

References ao2_t_alloc, ast_atomic_fetchadd_int(), ast_calloc, ast_cc_request_is_within_limits(), ast_channel_context(), ast_channel_datastore_add(), ast_channel_exten(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_free, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, cc_extension_monitor_init(), cc_interface_tree_destroy(), cc_ref(), cc_unref(), ast_cc_monitor::core_id, core_id_counter, ast_datastore::data, DATASTORE_INHERIT_FOREVER, dialed_cc_interfaces_info, ast_cc_monitor::id, ast_datastore::inheritance, interfaces, ast_datastore::next, and NULL.

Referenced by ast_cc_call_init().

◆ cc_monitor_destroy()

static void cc_monitor_destroy ( void *  data)
static

Definition at line 1854 of file ccss.c.

1855{
1856 struct ast_cc_monitor *monitor = data;
1857 /* During the monitor creation process, it is possible for this
1858 * function to be called prior to when callbacks are assigned
1859 * to the monitor. Also, extension monitors do not have callbacks
1860 * assigned to them, so we wouldn't want to segfault when we try
1861 * to destroy one of them.
1862 */
1863 ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n",
1864 monitor->core_id, monitor->interface->device_name);
1867 }
1868 if (monitor->callbacks) {
1869 monitor->callbacks->destructor(monitor->private_data);
1870 }
1871 cc_unref(monitor->interface, "Unreffing tree's reference to interface");
1872 ast_free(monitor->dialstring);
1873}
static void cc_extension_monitor_destructor(void *private_data)
Definition ccss.c:1838

References AST_CC_EXTENSION_MONITOR, ast_free, ast_log_dynamic_level, ast_cc_monitor::callbacks, cc_extension_monitor_destructor(), cc_logger_level, cc_unref(), ast_cc_monitor::core_id, ast_cc_monitor_callbacks::destructor, ast_cc_interface::device_name, ast_cc_monitor::dialstring, ast_cc_monitor::interface, ast_cc_interface::monitor_class, and ast_cc_monitor::private_data.

Referenced by cc_device_monitor_init(), and cc_extension_monitor_init().

◆ cc_monitor_failed()

static int cc_monitor_failed ( void *  data)
static

Definition at line 3943 of file ccss.c.

3944{
3945 struct ast_cc_monitor_failure_data *failure_data = data;
3946 struct cc_core_instance *core_instance;
3947 struct ast_cc_monitor *monitor_iter;
3948
3949 core_instance = find_cc_core_instance(failure_data->core_id);
3950 if (!core_instance) {
3951 /* Core instance no longer exists or invalid core_id. */
3953 "Core %d: Could not find core instance for device %s '%s'\n",
3954 failure_data->core_id, failure_data->device_name, failure_data->debug);
3955 ast_free((char *) failure_data->device_name);
3956 ast_free((char *) failure_data->debug);
3957 ast_free(failure_data);
3958 return -1;
3959 }
3960
3961 AST_LIST_LOCK(core_instance->monitors);
3962 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3963 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3964 if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) {
3966 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3967 monitor_iter->interface->device_name, 1);
3968 monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id);
3969 cc_publish_monitorfailed(monitor_iter->core_id, monitor_iter->interface->device_name);
3970 cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference.");
3971 }
3972 }
3973 }
3975
3976 if (!has_device_monitors(core_instance)) {
3977 ast_cc_failed(core_instance->core_id, "All monitors have failed\n");
3978 }
3979 AST_LIST_UNLOCK(core_instance->monitors);
3980 cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n");
3981
3982 ast_free((char *) failure_data->device_name);
3983 ast_free((char *) failure_data->debug);
3984 ast_free(failure_data);
3985 return 0;
3986}
static void cc_publish_monitorfailed(int core_id, const char *callee)
Definition ccss.c:1168

References AST_CC_DEVICE_MONITOR, ast_cc_failed(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_extension_monitor_change_is_valid(), cc_logger_level, cc_publish_monitorfailed(), cc_unref(), ast_cc_monitor::core_id, cc_core_instance::core_id, ast_cc_monitor_failure_data::core_id, ast_cc_monitor_failure_data::debug, ast_cc_interface::device_name, ast_cc_monitor_failure_data::device_name, find_cc_core_instance(), has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, ast_cc_monitor::next, and ast_cc_monitor::parent_id.

Referenced by ast_cc_monitor_failed().

◆ cc_offer()

static int cc_offer ( const int  core_id,
const char *const  debug,
  ... 
)
static

Definition at line 3769 of file ccss.c.

3770{
3771 va_list ap;
3772 int res;
3773
3774 va_start(ap, debug);
3775 res = cc_request_state_change(CC_CALLER_OFFERED, core_id, debug, ap);
3776 va_end(ap);
3777 return res;
3778}

References CC_CALLER_OFFERED, cc_request_state_change(), cc_recall_ds_data::core_id, and debug.

Referenced by ast_cc_offer().

◆ cc_party_b_free()

static int cc_party_b_free ( void *  data)
static

Definition at line 4092 of file ccss.c.

4093{
4094 struct cc_core_instance *core_instance = data;
4095 int res = 0;
4096
4097 if (core_instance->agent->callbacks->party_b_free) {
4098 res = core_instance->agent->callbacks->party_b_free(core_instance->agent);
4099 }
4100 cc_unref(core_instance, "Party B free finished. Unref core_instance");
4101 return res;
4102}
int(* party_b_free)(struct ast_cc_agent *agent)
Let the caller know that the callee has become free but that the caller cannot attempt to call back b...
Definition ccss.h:986

References cc_core_instance::agent, ast_cc_agent::callbacks, cc_unref(), and ast_cc_agent_callbacks::party_b_free.

Referenced by ast_cc_monitor_party_b_free().

◆ cc_publish()

static int cc_publish ( struct stasis_message_type message_type,
int  core_id,
struct ast_json extras 
)
static

Definition at line 1025 of file ccss.c.

1026{
1027 struct ast_json *blob;
1028 struct ast_json_payload *payload;
1029 struct stasis_message *message;
1030
1031 if (!message_type) {
1032 return -1;
1033 }
1034
1035 blob = ast_json_pack("{s: i}",
1036 "core_id", core_id);
1037 if (!blob) {
1038 return -1;
1039 }
1040
1041 if (extras) {
1042 ast_json_object_update(blob, extras);
1043 }
1044
1045 payload = ast_json_payload_create(blob);
1046 ast_json_unref(blob);
1047
1048 if (!payload) {
1049 return -1;
1050 }
1051
1052 message = stasis_message_create(message_type, payload);
1053 ao2_ref(payload, -1);
1054
1055 if (!message) {
1056 return -1;
1057 }
1058
1060 ao2_ref(message, -1);
1061
1062 return 0;
1063}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json_payload * ast_json_payload_create(struct ast_json *json)
Create an ao2 object to pass json blobs as data payloads for stasis.
Definition json.c:756
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
int ast_json_object_update(struct ast_json *object, struct ast_json *other)
Update object with all of the fields of other.
Definition json.c:426
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition stasis.c:1578
struct stasis_topic * ast_system_topic(void)
A Stasis Message Bus API topic which publishes messages regarding system changes.
Abstract JSON element (object, array, string, int, ...).

References ao2_ref, ast_json_object_update(), ast_json_pack(), ast_json_payload_create(), ast_json_unref(), ast_system_topic(), stasis_message_create(), and stasis_publish().

Referenced by cc_publish_available(), cc_publish_callerrecalling(), cc_publish_callerstartmonitoring(), cc_publish_callerstopmonitoring(), cc_publish_failure(), cc_publish_monitorfailed(), cc_publish_offertimerstart(), cc_publish_recallcomplete(), cc_publish_requestacknowledged(), and cc_publish_requested().

◆ cc_publish_available()

static void cc_publish_available ( int  core_id,
const char *  callee,
const char *  service 
)
static

Definition at line 1065 of file ccss.c.

1066{
1067 struct ast_json *extras;
1068
1069 extras = ast_json_pack("{s: s, s: s}",
1070 "callee", callee,
1071 "service", service);
1072
1073 cc_publish(ast_cc_available_type(), core_id, extras);
1074 ast_json_unref(extras);
1075}
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition ccss.c:1025
struct stasis_message_type * ast_cc_available_type(void)
A stasis_message_type for CCSS Available messages.

References ast_cc_available_type(), ast_json_pack(), ast_json_unref(), cc_publish(), and service.

Referenced by ast_handle_cc_control_frame().

◆ cc_publish_callerrecalling()

static void cc_publish_callerrecalling ( int  core_id,
const char *  caller 
)
static

Definition at line 1134 of file ccss.c.

1135{
1136 struct ast_json *extras;
1137
1138 extras = ast_json_pack("{s: s}",
1139 "caller", caller);
1140
1141 cc_publish(ast_cc_callerrecalling_type(), core_id, extras);
1142 ast_json_unref(extras);
1143}
struct stasis_message_type * ast_cc_callerrecalling_type(void)
A stasis_message_type for CCSS Caller Recalling messages.

References ast_cc_callerrecalling_type(), ast_json_pack(), ast_json_unref(), and cc_publish().

Referenced by cc_recalling().

◆ cc_publish_callerstartmonitoring()

static void cc_publish_callerstartmonitoring ( int  core_id,
const char *  caller 
)
static

Definition at line 1123 of file ccss.c.

1124{
1125 struct ast_json *extras;
1126
1127 extras = ast_json_pack("{s: s}",
1128 "caller", caller);
1129
1131 ast_json_unref(extras);
1132}
struct stasis_message_type * ast_cc_callerstartmonitoring_type(void)
A stasis_message_type for CCSS Caller Start Monitoring messages.

References ast_cc_callerstartmonitoring_type(), ast_json_pack(), ast_json_unref(), and cc_publish().

Referenced by cc_caller_busy().

◆ cc_publish_callerstopmonitoring()

static void cc_publish_callerstopmonitoring ( int  core_id,
const char *  caller 
)
static

Definition at line 1112 of file ccss.c.

1113{
1114 struct ast_json *extras;
1115
1116 extras = ast_json_pack("{s: s}",
1117 "caller", caller);
1118
1119 cc_publish(ast_cc_callerstopmonitoring_type(), core_id, extras);
1120 ast_json_unref(extras);
1121}
struct stasis_message_type * ast_cc_callerstopmonitoring_type(void)
A stasis_message_type for CCSS Caller Stop Monitoring messages.

References ast_cc_callerstopmonitoring_type(), ast_json_pack(), ast_json_unref(), and cc_publish().

Referenced by cc_active().

◆ cc_publish_failure()

static void cc_publish_failure ( int  core_id,
const char *  caller,
const char *  reason 
)
static

Definition at line 1156 of file ccss.c.

1157{
1158 struct ast_json *extras;
1159
1160 extras = ast_json_pack("{s: s, s: s}",
1161 "caller", caller,
1162 "reason", reason);
1163
1164 cc_publish(ast_cc_failure_type(), core_id, extras);
1165 ast_json_unref(extras);
1166}
struct stasis_message_type * ast_cc_failure_type(void)
A stasis_message_type for CCSS Failure messages.

References ast_cc_failure_type(), ast_json_pack(), ast_json_unref(), and cc_publish().

Referenced by cc_failed().

◆ cc_publish_monitorfailed()

static void cc_publish_monitorfailed ( int  core_id,
const char *  callee 
)
static

Definition at line 1168 of file ccss.c.

1169{
1170 struct ast_json *extras;
1171
1172 extras = ast_json_pack("{s: s}",
1173 "callee", callee);
1174
1175 cc_publish(ast_cc_monitorfailed_type(), core_id, extras);
1176 ast_json_unref(extras);
1177}
struct stasis_message_type * ast_cc_monitorfailed_type(void)
A stasis_message_type for CCSS Monitor Failed messages.

References ast_cc_monitorfailed_type(), ast_json_pack(), ast_json_unref(), and cc_publish().

Referenced by cc_monitor_failed().

◆ cc_publish_offertimerstart()

static void cc_publish_offertimerstart ( int  core_id,
const char *  caller,
unsigned int  expires 
)
static

Definition at line 1077 of file ccss.c.

1078{
1079 struct ast_json *extras;
1080
1081 extras = ast_json_pack("{s: s, s: I}",
1082 "caller", caller,
1083 "expires", (ast_json_int_t)expires);
1084
1085 cc_publish(ast_cc_offertimerstart_type(), core_id, extras);
1086 ast_json_unref(extras);
1087}
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition json.h:87
struct stasis_message_type * ast_cc_offertimerstart_type(void)
A stasis_message_type for CCSS Offer Timer Start messages.

References ast_cc_offertimerstart_type(), ast_json_pack(), ast_json_unref(), and cc_publish().

Referenced by cc_caller_offered().

◆ cc_publish_recallcomplete()

static void cc_publish_recallcomplete ( int  core_id,
const char *  caller 
)
static

Definition at line 1145 of file ccss.c.

1146{
1147 struct ast_json *extras;
1148
1149 extras = ast_json_pack("{s: s}",
1150 "caller", caller);
1151
1152 cc_publish(ast_cc_recallcomplete_type(), core_id, extras);
1153 ast_json_unref(extras);
1154}
struct stasis_message_type * ast_cc_recallcomplete_type(void)
A stasis_message_type for CCSS Recall Complete messages.

References ast_cc_recallcomplete_type(), ast_json_pack(), ast_json_unref(), and cc_publish().

Referenced by cc_complete().

◆ cc_publish_requestacknowledged()

static void cc_publish_requestacknowledged ( int  core_id,
const char *  caller 
)
static

Definition at line 1101 of file ccss.c.

1102{
1103 struct ast_json *extras;
1104
1105 extras = ast_json_pack("{s: s}",
1106 "caller", caller);
1107
1108 cc_publish(ast_cc_requestacknowledged_type(), core_id, extras);
1109 ast_json_unref(extras);
1110}
struct stasis_message_type * ast_cc_requestacknowledged_type(void)
A stasis_message_type for CCSS Request Acknowledged messages.

References ast_cc_requestacknowledged_type(), ast_json_pack(), ast_json_unref(), and cc_publish().

Referenced by cc_active().

◆ cc_publish_requested()

static void cc_publish_requested ( int  core_id,
const char *  caller,
const char *  callee 
)
static

Definition at line 1089 of file ccss.c.

1090{
1091 struct ast_json *extras;
1092
1093 extras = ast_json_pack("{s: s, s: s}",
1094 "caller", caller,
1095 "callee", callee);
1096
1097 cc_publish(ast_cc_requested_type(), core_id, extras);
1098 ast_json_unref(extras);
1099}
struct stasis_message_type * ast_cc_requested_type(void)
A stasis_message_type for CCSS Requested messages.

References ast_cc_requested_type(), ast_json_pack(), ast_json_unref(), and cc_publish().

Referenced by request_cc().

◆ cc_recall_ds_destroy()

static void cc_recall_ds_destroy ( void *  data)
static

Definition at line 3410 of file ccss.c.

3411{
3412 struct cc_recall_ds_data *recall_data = data;
3413 recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree");
3414 ast_free(recall_data);
3415}

References ast_free, cc_unref(), and cc_recall_ds_data::interface_tree.

◆ cc_recall_ds_duplicate()

static void * cc_recall_ds_duplicate ( void *  data)
static

Definition at line 3396 of file ccss.c.

3397{
3398 struct cc_recall_ds_data *old_data = data;
3399 struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data));
3400
3401 if (!new_data) {
3402 return NULL;
3403 }
3404 new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate");
3405 new_data->core_id = old_data->core_id;
3406 new_data->nested = 1;
3407 return new_data;
3408}

References ast_calloc, cc_ref(), cc_recall_ds_data::core_id, cc_recall_ds_data::interface_tree, cc_recall_ds_data::nested, and NULL.

◆ cc_recalling()

static int cc_recalling ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3266 of file ccss.c.

3267{
3268 /* Both caller and callee are available, call agent's recall callback
3269 */
3270 cancel_available_timer(core_instance);
3271 cc_publish_callerrecalling(core_instance->core_id, core_instance->agent->device_name);
3272 return 0;
3273}
static void cancel_available_timer(struct cc_core_instance *core_instance)
Definition ccss.c:3244
static void cc_publish_callerrecalling(int core_id, const char *caller)
Definition ccss.c:1134

References cc_core_instance::agent, cancel_available_timer(), cc_publish_callerrecalling(), cc_core_instance::core_id, and ast_cc_agent::device_name.

◆ cc_ref()

static void * cc_ref ( void *  obj,
const char *  debug 
)
inlinestatic

◆ cc_request_state_change()

static int cc_request_state_change ( enum cc_state  state,
const int  core_id,
const char *  debug,
va_list  ap 
)
static

Definition at line 3346 of file ccss.c.

3347{
3348 int res;
3349 int debuglen;
3350 char dummy[1];
3351 va_list aq;
3352 struct cc_core_instance *core_instance;
3353 struct cc_state_change_args *args;
3354 /* This initial call to vsnprintf is simply to find what the
3355 * size of the string needs to be
3356 */
3357 va_copy(aq, ap);
3358 /* We add 1 to the result since vsnprintf's return does not
3359 * include the terminating null byte
3360 */
3361 debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1;
3362 va_end(aq);
3363
3364 if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) {
3365 return -1;
3366 }
3367
3369 if (!core_instance) {
3370 ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n",
3371 core_id);
3372 ast_free(args);
3373 return -1;
3374 }
3375
3376 args->core_instance = core_instance;
3377 args->state = state;
3378 args->core_id = core_id;
3379 vsnprintf(args->debug, debuglen, debug, ap);
3380
3382 if (res) {
3383 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3384 ast_free(args);
3385 }
3386 return res;
3387}
static int cc_do_state_change(void *datap)
Definition ccss.c:3303
enum cc_state state
Definition ccss.c:409
static void dummy(char *unused,...)
struct cc_core_instance * core_instance
Definition ccss.c:3013

References args, ast_calloc, ast_free, ast_log_dynamic_level, ast_taskprocessor_push(), cc_core_taskprocessor, cc_do_state_change(), cc_logger_level, cc_unref(), cc_core_instance::core_id, cc_state_change_args::core_id, cc_state_change_args::core_instance, debug, dummy(), find_cc_core_instance(), and state.

Referenced by ast_cc_agent_accept_request(), ast_cc_agent_caller_available(), ast_cc_agent_caller_busy(), ast_cc_agent_recalling(), ast_cc_completed(), ast_cc_failed(), ast_cc_monitor_callee_available(), ast_cc_monitor_request_acked(), and cc_offer().

◆ cc_service_to_string()

static const char * cc_service_to_string ( enum ast_cc_service_type  service)
static

Definition at line 428 of file ccss.c.

429{
430 return cc_service_to_string_map[service].service_string;
431}
static const struct @341 cc_service_to_string_map[]

References cc_service_to_string_map, and service.

Referenced by ast_handle_cc_control_frame(), and cc_cli_print_monitor_stats().

◆ cc_state_to_devstate()

static enum ast_device_state cc_state_to_devstate ( enum cc_state  state)
static

Definition at line 603 of file ccss.c.

604{
606}
static enum ast_device_state cc_state_to_devstate_map[]
Definition ccss.c:582

References cc_state_to_devstate_map, and state.

Referenced by ccss_device_state(), and ccss_notify_device_state_change().

◆ cc_state_to_string()

static const char * cc_state_to_string ( enum cc_state  state)
static

Definition at line 423 of file ccss.c.

424{
425 return cc_state_to_string_map[state].state_string;
426}
static const struct @342 cc_state_to_string_map[]

References cc_state_to_string_map, and state.

Referenced by cc_do_state_change(), ccss_device_state(), ccss_notify_device_state_change(), and print_stats_cb().

◆ cc_status_request()

static int cc_status_request ( void *  data)
static

Definition at line 4025 of file ccss.c.

4026{
4027 struct cc_core_instance *core_instance= data;
4028 int res;
4029
4030 res = core_instance->agent->callbacks->status_request(core_instance->agent);
4031 cc_unref(core_instance, "Status request finished. Unref core instance");
4032 return res;
4033}
int(* status_request)(struct ast_cc_agent *agent)
Request the status of the agent's device.
Definition ccss.h:943

References cc_core_instance::agent, ast_cc_agent::callbacks, cc_unref(), and ast_cc_agent_callbacks::status_request.

Referenced by ast_cc_monitor_status_request().

◆ cc_status_response()

static int cc_status_response ( void *  data)
static

Definition at line 4127 of file ccss.c.

4128{
4129 struct cc_status_response_args *args = data;
4130 struct cc_core_instance *core_instance = args->core_instance;
4131 struct ast_cc_monitor *monitor_iter;
4132 enum ast_device_state devstate = args->devstate;
4133
4134 ast_free(args);
4135
4136 AST_LIST_LOCK(core_instance->monitors);
4137 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
4138 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR &&
4139 monitor_iter->callbacks->status_response) {
4140 monitor_iter->callbacks->status_response(monitor_iter, devstate);
4141 }
4142 }
4143 AST_LIST_UNLOCK(core_instance->monitors);
4144 cc_unref(core_instance, "Status response finished. Unref core instance");
4145 return 0;
4146}
int(* status_response)(struct ast_cc_monitor *monitor, enum ast_device_state devstate)
Status response to an ast_cc_monitor_status_request().
Definition ccss.h:594

References args, AST_CC_DEVICE_MONITOR, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_unref(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, ast_cc_monitor::next, and ast_cc_monitor_callbacks::status_response.

Referenced by ast_cc_agent_status_response().

◆ cc_stop_ringing()

static int cc_stop_ringing ( void *  data)
static

Definition at line 4053 of file ccss.c.

4054{
4055 struct cc_core_instance *core_instance = data;
4056 int res = 0;
4057
4058 if (core_instance->agent->callbacks->stop_ringing) {
4059 res = core_instance->agent->callbacks->stop_ringing(core_instance->agent);
4060 }
4061 /* If an agent is being asked to stop ringing, then he needs to be prepared if for
4062 * whatever reason he needs to be called back again. The proper state to be in to
4063 * detect such a circumstance is the CC_ACTIVE state.
4064 *
4065 * We get to this state using the slightly unintuitive method of calling
4066 * ast_cc_monitor_request_acked because it gets us to the proper state.
4067 */
4068 ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.",
4069 core_instance->agent->device_name);
4070 cc_unref(core_instance, "Stop ringing finished. Unref core_instance");
4071 return res;
4072}
int(* stop_ringing)(struct ast_cc_agent *agent)
Request for an agent's phone to stop ringing.
Definition ccss.h:965

References cc_core_instance::agent, ast_cc_monitor_request_acked(), ast_cc_agent::callbacks, cc_unref(), cc_core_instance::core_id, ast_cc_agent::device_name, and ast_cc_agent_callbacks::stop_ringing.

Referenced by ast_cc_monitor_stop_ringing().

◆ cc_unique_append()

static void cc_unique_append ( struct ast_str **  str,
const char *  dialstring 
)
static

Definition at line 3582 of file ccss.c.

3583{
3584 char dialstring_search[AST_CHANNEL_NAME + 1];
3585
3586 if (ast_strlen_zero(dialstring)) {
3587 /* No dialstring to append. */
3588 return;
3589 }
3590 snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&');
3591 if (strstr(ast_str_buffer(*str), dialstring_search)) {
3592 return;
3593 }
3594 ast_str_append(str, 0, "%s", dialstring_search);
3595}
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition strings.h:1139

References AST_CHANNEL_NAME, ast_str_append(), ast_str_buffer(), ast_strlen_zero(), ast_cc_monitor::dialstring, and str.

Referenced by build_cc_interfaces_chanvar().

◆ cc_unref()

static void * cc_unref ( void *  obj,
const char *  debug 
)
inlinestatic

◆ cccancel_exec()

static int cccancel_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 4378 of file ccss.c.

4379{
4380 struct cc_core_instance *core_instance;
4381 char device_name[AST_CHANNEL_NAME];
4382 unsigned long match_flags;
4383 int res;
4384
4385 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4386
4388 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) {
4389 ast_log_dynamic_level(cc_logger_level, "Cannot find CC transaction to cancel for caller %s\n", device_name);
4390 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4391 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NO_CORE_INSTANCE");
4392 return 0;
4393 }
4394
4395 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4396 ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calls with a generic agent\n");
4397 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4398 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4399 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NOT_GENERIC");
4400 return 0;
4401 }
4402 res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s",
4403 core_instance->core_id, device_name);
4404 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4405 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", res ? "FAIL" : "SUCCESS");
4406 if (res) {
4407 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "UNSPECIFIED");
4408 }
4409 return 0;
4410}
#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container....
Definition astobj2.h:1721
match_flags
Definition ccss.c:488
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition ccss.c:511

References cc_core_instance::agent, ao2_t_callback_data, ast_cc_failed(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_log, ast_log_dynamic_level, ast_cc_agent::callbacks, cc_core_instances, cc_logger_level, cc_unref(), cc_core_instance::core_id, LOG_WARNING, match_agent(), MATCH_REQUEST, pbx_builtin_setvar_helper(), and ast_cc_agent_callbacks::type.

Referenced by load_module().

◆ ccreq_exec()

static int ccreq_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 4327 of file ccss.c.

4328{
4329 struct cc_core_instance *core_instance;
4330 char device_name[AST_CHANNEL_NAME];
4331 unsigned long match_flags;
4332 int res;
4333
4334 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4335
4337 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) {
4338 ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name);
4339 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4340 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NO_CORE_INSTANCE");
4341 return 0;
4342 }
4343
4344 ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n",
4345 core_instance->core_id, device_name);
4346
4347 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4348 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n",
4349 core_instance->core_id);
4350 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4351 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NOT_GENERIC");
4352 cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent");
4353 return 0;
4354 }
4355
4357 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n",
4358 core_instance->core_id);
4359 ast_cc_failed(core_instance->core_id, "Too many CC requests\n");
4360 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4361 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "TOO_MANY_REQUESTS");
4362 cc_unref(core_instance, "Unref core_instance since too many CC requests");
4363 return 0;
4364 }
4365
4366 res = ast_cc_agent_accept_request(core_instance->core_id, "CallCompletionRequest called by caller %s for core_id %d", device_name, core_instance->core_id);
4367 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS");
4368 if (res) {
4369 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "UNSPECIFIED");
4370 }
4371
4372 cc_unref(core_instance, "Done with CallCompletionRequest");
4373 return 0;
4374}
int ast_cc_agent_accept_request(int core_id, const char *const debug,...)
Accept inbound CC request.
Definition ccss.c:3807

References cc_core_instance::agent, ao2_t_callback_data, ast_cc_agent_accept_request(), ast_cc_failed(), ast_cc_request_is_within_limits(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_log_dynamic_level, ast_cc_agent::callbacks, cc_core_instances, cc_logger_level, cc_unref(), cc_core_instance::core_id, match_agent(), MATCH_NO_REQUEST, pbx_builtin_setvar_helper(), and ast_cc_agent_callbacks::type.

Referenced by load_module().

◆ ccss_device_state()

static enum ast_device_state ccss_device_state ( const char *  device_name)
static

Definition at line 619 of file ccss.c.

620{
621 struct cc_core_instance *core_instance;
622 unsigned long match_flags;
623 enum ast_device_state cc_current_state;
624
627 (char *) device_name, &match_flags,
628 "Find Core Instance for ccss_device_state request.");
629 if (!core_instance) {
631 "Couldn't find a core instance for caller %s\n", device_name);
633 }
634
636 "Core %d: Found core_instance for caller %s in state %s\n",
637 core_instance->core_id, device_name, cc_state_to_string(core_instance->current_state));
638
639 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
641 "Core %d: Device State is only for generic agent types.\n",
642 core_instance->core_id);
643 cc_unref(core_instance, "Unref core_instance since ccss_device_state was called with native agent");
645 }
646 cc_current_state = cc_state_to_devstate(core_instance->current_state);
647 cc_unref(core_instance, "Unref core_instance done with ccss_device_state");
648 return cc_current_state;
649}
static enum ast_device_state cc_state_to_devstate(enum cc_state state)
Definition ccss.c:603

References cc_core_instance::agent, ao2_t_callback_data, ast_log_dynamic_level, ast_cc_agent::callbacks, cc_core_instances, CC_FAILED, cc_logger_level, cc_state_to_devstate(), cc_state_to_string(), cc_unref(), cc_core_instance::core_id, cc_core_instance::current_state, match_agent(), MATCH_NO_REQUEST, and ast_cc_agent_callbacks::type.

Referenced by load_module().

◆ ccss_notify_device_state_change()

static void ccss_notify_device_state_change ( const char *  device,
enum cc_state  state 
)
static

Definition at line 660 of file ccss.c.

661{
662 enum ast_device_state devstate;
663
664 devstate = cc_state_to_devstate(state);
665
667 "Notification of CCSS state change to '%s', device state '%s' for device '%s'\n",
668 cc_state_to_string(state), ast_devstate2str(devstate), device);
669
670 ast_devstate_changed(devstate, AST_DEVSTATE_CACHABLE, "ccss:%s", device);
671}
@ AST_DEVSTATE_CACHABLE
Definition devicestate.h:70
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.

References ast_devstate2str(), AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_log_dynamic_level, cc_logger_level, cc_state_to_devstate(), and cc_state_to_string().

Referenced by cc_do_state_change().

◆ check_callback_sanity()

static void check_callback_sanity ( const struct ast_cc_agent_callbacks callbacks)
static

Definition at line 2561 of file ccss.c.

2562{
2563 ast_assert(callbacks->init != NULL);
2564 ast_assert(callbacks->start_offer_timer != NULL);
2565 ast_assert(callbacks->stop_offer_timer != NULL);
2566 ast_assert(callbacks->respond != NULL);
2567 ast_assert(callbacks->status_request != NULL);
2568 ast_assert(callbacks->start_monitoring != NULL);
2569 ast_assert(callbacks->callee_available != NULL);
2570 ast_assert(callbacks->destructor != NULL);
2571}

References ast_assert, callbacks, and NULL.

Referenced by cc_agent_init().

◆ complete_core_id()

static char * complete_core_id ( const char *  word)
static

Definition at line 4639 of file ccss.c.

4640{
4641 int wordlen = strlen(word);
4642 struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0);
4643 struct cc_core_instance *core_instance;
4644
4645 for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance"));
4646 cc_unref(core_instance, "CLI tab completion iteration")) {
4647 char core_id_str[20];
4648 snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id);
4649 if (!strncmp(word, core_id_str, wordlen)) {
4650 if (ast_cli_completion_add(ast_strdup(core_id_str))) {
4651 cc_unref(core_instance, "Found a matching core ID for CLI tab-completion");
4652 break;
4653 }
4654 }
4655 }
4656 ao2_iterator_destroy(&core_iter);
4657
4658 return NULL;
4659}
#define ao2_t_iterator_next(iter, tag)
Definition astobj2.h:1909
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition main/cli.c:2737
short word
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_cli_completion_add(), ast_strdup, cc_core_instances, cc_unref(), cc_core_instance::core_id, and NULL.

Referenced by handle_cc_kill().

◆ count_agents()

static long count_agents ( const char *const  caller,
const int  core_id_exception 
)
static

Definition at line 2535 of file ccss.c.

2536{
2538
2539 ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents");
2540 ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count);
2541 return data.count;
2542}
static int count_agents_cb(void *obj, void *arg, void *data, int flags)
Definition ccss.c:549

References ao2_t_callback_data, ast_log_dynamic_level, cc_core_instances, cc_logger_level, count_agents_cb_data::core_id_exception, count_agents_cb_data::count, count_agents_cb(), and OBJ_NODATA.

Referenced by cc_core_init_instance().

◆ count_agents_cb()

static int count_agents_cb ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 549 of file ccss.c.

550{
551 struct cc_core_instance *core_instance = obj;
552 const char *name = arg;
553 struct count_agents_cb_data *cb_data = data;
554
555 if (cb_data->core_id_exception == core_instance->core_id) {
556 ast_log_dynamic_level(cc_logger_level, "Found agent with core_id %d but not counting it toward total\n", core_instance->core_id);
557 return 0;
558 }
559
560 if (core_instance->current_state >= CC_CALLER_REQUESTED && !strcmp(core_instance->agent->device_name, name)) {
561 cb_data->count++;
562 }
563 return 0;
564}

References cc_core_instance::agent, ast_log_dynamic_level, CC_CALLER_REQUESTED, cc_logger_level, cc_core_instance::core_id, count_agents_cb_data::core_id_exception, count_agents_cb_data::count, cc_core_instance::current_state, ast_cc_agent::device_name, and name.

Referenced by count_agents().

◆ count_monitors_cb()

static int count_monitors_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 4418 of file ccss.c.

4419{
4420 struct cc_core_instance *core_instance = obj;
4421 struct count_monitors_cb_data *cb_data = arg;
4422 const char *device_name = cb_data->device_name;
4423 const char *monitor_type = cb_data->monitor_type;
4424 struct ast_cc_monitor *monitor_iter;
4425
4426 AST_LIST_LOCK(core_instance->monitors);
4427 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
4428 if (!strcmp(monitor_iter->interface->device_name, device_name) &&
4429 !strcmp(monitor_iter->interface->monitor_type, monitor_type)) {
4430 cb_data->count++;
4431 break;
4432 }
4433 }
4434 AST_LIST_UNLOCK(core_instance->monitors);
4435 return 0;
4436}
const char * monitor_type
Definition ccss.c:4414

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, count_monitors_cb_data::count, ast_cc_interface::device_name, count_monitors_cb_data::device_name, ast_cc_monitor::interface, ast_cc_interface::monitor_type, count_monitors_cb_data::monitor_type, cc_core_instance::monitors, and ast_cc_monitor::next.

Referenced by ast_cc_monitor_count().

◆ create_new_generic_list()

static struct generic_monitor_instance_list * create_new_generic_list ( struct ast_cc_monitor monitor)
static

Definition at line 1423 of file ccss.c.

1424{
1425 struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list),
1426 generic_monitor_instance_list_destructor, "allocate generic monitor instance list");
1427 char * device_name;
1428 struct stasis_topic *device_specific_topic;
1429
1430 if (!generic_list) {
1431 return NULL;
1432 }
1433
1434 if (!(device_name = ast_strdup(monitor->interface->device_name))) {
1435 cc_unref(generic_list, "Failed to strdup the monitor's device name");
1436 return NULL;
1437 }
1438 ast_tech_to_upper(device_name);
1439 generic_list->device_name = device_name;
1440
1441 device_specific_topic = ast_device_state_topic(device_name);
1442 if (!device_specific_topic) {
1443 return NULL;
1444 }
1445
1446 if (!(generic_list->sub = stasis_subscribe(device_specific_topic, generic_monitor_devstate_cb, NULL))) {
1447 cc_unref(generic_list, "Failed to subscribe to device state");
1448 return NULL;
1449 }
1452 generic_list->current_state = ast_device_state(monitor->interface->device_name);
1453 ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list");
1454 return generic_list;
1455}
static void generic_monitor_instance_list_destructor(void *obj)
Definition ccss.c:1410
static void generic_monitor_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Definition ccss.c:1498
char * ast_tech_to_upper(char *dev_str)
Convert the tech portion of a device string to upper case.
Definition strings.h:1236
struct stasis_subscription * sub
Definition ccss.c:1375

References ao2_t_alloc, ao2_t_link, ast_device_state_message_type(), ast_device_state_topic(), ast_strdup, ast_tech_to_upper(), cc_unref(), generic_monitor_instance_list::current_state, ast_cc_interface::device_name, generic_monitor_instance_list::device_name, generic_monitor_devstate_cb(), generic_monitor_instance_list_destructor(), generic_monitors, ast_cc_monitor::interface, NULL, stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), and generic_monitor_instance_list::sub.

Referenced by cc_generic_monitor_request_cc().

◆ dialed_cc_interfaces_destroy()

static void dialed_cc_interfaces_destroy ( void *  data)
static

Definition at line 1961 of file ccss.c.

1962{
1963 struct dialed_cc_interfaces *cc_interfaces = data;
1964 cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree");
1965 ast_free(cc_interfaces);
1966}

References ast_free, cc_unref(), and dialed_cc_interfaces::interface_tree.

◆ dialed_cc_interfaces_duplicate()

static void * dialed_cc_interfaces_duplicate ( void *  data)
static

Definition at line 1981 of file ccss.c.

1982{
1983 struct dialed_cc_interfaces *old_cc_interfaces = data;
1984 struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces));
1985 if (!new_cc_interfaces) {
1986 return NULL;
1987 }
1988 new_cc_interfaces->ignore = old_cc_interfaces->ignore;
1989 new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id;
1990 new_cc_interfaces->is_original_caller = 0;
1991 cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree");
1992 new_cc_interfaces->core_id = old_cc_interfaces->core_id;
1993 new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree;
1994 return new_cc_interfaces;
1995}

References ast_calloc, cc_ref(), dialed_cc_interfaces::core_id, dialed_cc_interfaces::dial_parent_id, dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, dialed_cc_interfaces::is_original_caller, and NULL.

◆ extension_monitor_pvt_init()

static struct extension_monitor_pvt * extension_monitor_pvt_init ( void  )
static

Definition at line 2012 of file ccss.c.

2013{
2014 struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt));
2015 if (!ext_pvt) {
2016 return NULL;
2017 }
2019 return ext_pvt;
2020}
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.

References ast_calloc, AST_LIST_HEAD_INIT_NOLOCK, extension_monitor_pvt::child_dialstrings, and NULL.

Referenced by cc_extension_monitor_init().

◆ find_agent_callbacks()

static const struct ast_cc_agent_callbacks * find_agent_callbacks ( struct ast_channel chan)
static

Definition at line 1283 of file ccss.c.

1284{
1285 struct cc_agent_backend *backend;
1286 const struct ast_cc_agent_callbacks *callbacks = NULL;
1287 struct ast_cc_config_params *cc_params;
1288 char type[32];
1289
1290 cc_params = ast_channel_get_cc_config_params(chan);
1291 if (!cc_params) {
1292 return NULL;
1293 }
1294 switch (ast_get_cc_agent_policy(cc_params)) {
1296 ast_copy_string(type, "generic", sizeof(type));
1297 break;
1299 ast_channel_get_cc_agent_type(chan, type, sizeof(type));
1300 break;
1301 default:
1302 ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n");
1303 return NULL;
1304 }
1305
1307 AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) {
1308 if (!strcmp(backend->callbacks->type, type)) {
1309 ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type);
1310 callbacks = backend->callbacks;
1311 break;
1312 }
1313 }
1315 return callbacks;
1316}
int ast_channel_get_cc_agent_type(struct ast_channel *chan, char *agent_type, size_t size)
Find the appropriate CC agent type to use given a channel.
Definition channel.c:10561
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition linkedlists.h:78
#define AST_RWLIST_TRAVERSE

References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, ast_channel_get_cc_agent_type(), ast_channel_get_cc_config_params(), ast_copy_string(), ast_get_cc_agent_policy(), ast_log_dynamic_level, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, cc_agent_backend::callbacks, callbacks, cc_logger_level, NULL, type, and ast_cc_agent_callbacks::type.

Referenced by cc_agent_init().

◆ find_cc_core_instance()

static struct cc_core_instance * find_cc_core_instance ( const int  core_id)
static

◆ find_generic_monitor_instance_list()

static struct generic_monitor_instance_list * find_generic_monitor_instance_list ( const char *const  device_name)
static

Definition at line 1400 of file ccss.c.

1401{
1402 struct generic_monitor_instance_list finder = {0};
1403 char *uppertech = ast_strdupa(device_name);
1404 ast_tech_to_upper(uppertech);
1405 finder.device_name = uppertech;
1406
1407 return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list");
1408}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298

References ao2_t_find, ast_strdupa, ast_tech_to_upper(), generic_monitor_instance_list::device_name, generic_monitors, and OBJ_POINTER.

Referenced by cc_generic_monitor_destructor(), cc_generic_monitor_request_cc(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), and generic_monitor_devstate_tp_cb().

◆ find_monitor_callbacks()

static const struct ast_cc_monitor_callbacks * find_monitor_callbacks ( const char *const  type)
static

Definition at line 1205 of file ccss.c.

1206{
1207 struct cc_monitor_backend *backend;
1208 const struct ast_cc_monitor_callbacks *callbacks = NULL;
1209
1211 AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) {
1212 if (!strcmp(backend->callbacks->type, type)) {
1213 ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type);
1214 callbacks = backend->callbacks;
1215 break;
1216 }
1217 }
1219 return callbacks;
1220}
const char * type
Type of monitor the callbacks belong to.
Definition ccss.h:549

References ast_log_dynamic_level, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, cc_monitor_backend::callbacks, callbacks, cc_logger_level, NULL, type, and ast_cc_monitor_callbacks::type.

Referenced by call_destructor_with_no_monitor(), and cc_device_monitor_init().

◆ generic_agent_devstate_cb()

static void generic_agent_devstate_cb ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 2790 of file ccss.c.

2791{
2792 struct ast_cc_agent *agent = userdata;
2793 enum ast_device_state new_state;
2794 struct ast_device_state_message *dev_state;
2795 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2796
2798 cc_unref(agent, "Done holding ref for subscription");
2799 return;
2801 return;
2802 }
2803
2804 dev_state = stasis_message_data(msg);
2805 if (dev_state->eid) {
2806 /* ignore non-aggregate states */
2807 return;
2808 }
2809
2810 new_state = dev_state->state;
2811 if (!cc_generic_is_device_available(new_state)) {
2812 /* Not interested in this new state of the device. It is still busy. */
2813 return;
2814 }
2815
2816 generic_pvt->sub = stasis_unsubscribe(sub);
2817 ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name);
2818}
int ast_cc_agent_caller_available(int core_id, const char *const debug,...)
Indicate that a previously unavailable caller has become available.
Definition ccss.c:3859
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
Definition stasis.c:1241
The structure that contains device state.
enum ast_device_state state
const struct ast_eid * eid
The EID of the server where this message originated.

References ast_cc_agent_caller_available(), ast_device_state_message_type(), cc_generic_is_device_available(), cc_unref(), ast_cc_agent::core_id, ast_cc_agent::device_name, ast_device_state_message::eid, ast_cc_agent::private_data, stasis_message_data(), stasis_subscription_final_message(), stasis_unsubscribe(), ast_device_state_message::state, cc_generic_agent_pvt::sub, and sub.

Referenced by cc_generic_agent_start_monitoring().

◆ generic_monitor_devstate_cb()

static void generic_monitor_devstate_cb ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 1498 of file ccss.c.

1499{
1500 /* Wow, it's cool that we've picked up on a state change, but we really want
1501 * the actual work to be done in the core's taskprocessor execution thread
1502 * so that all monitor operations can be serialized. Locks?! We don't need
1503 * no steenkin' locks!
1504 */
1505 struct ast_device_state_message *dev_state;
1507 return;
1508 }
1509
1510 dev_state = stasis_message_data(msg);
1511 if (dev_state->eid) {
1512 /* ignore non-aggregate states */
1513 return;
1514 }
1515
1516 ao2_t_ref(dev_state, +1, "Bumping dev_state ref for cc_core_taskprocessor");
1518 ao2_cleanup(dev_state);
1519 return;
1520 }
1521}
#define ao2_cleanup(obj)
Definition astobj2.h:1934
static int generic_monitor_devstate_tp_cb(void *data)
Definition ccss.c:1457

References ao2_cleanup, ao2_t_ref, ast_device_state_message_type(), ast_taskprocessor_push(), cc_core_taskprocessor, ast_device_state_message::eid, generic_monitor_devstate_tp_cb(), and stasis_message_data().

Referenced by create_new_generic_list().

◆ generic_monitor_devstate_tp_cb()

static int generic_monitor_devstate_tp_cb ( void *  data)
static

Definition at line 1457 of file ccss.c.

1458{
1459 RAII_VAR(struct ast_device_state_message *, dev_state, data, ao2_cleanup);
1460 enum ast_device_state new_state = dev_state->state;
1461 enum ast_device_state previous_state;
1462 struct generic_monitor_instance_list *generic_list;
1463 struct generic_monitor_instance *generic_instance;
1464
1465 if (!(generic_list = find_generic_monitor_instance_list(dev_state->device))) {
1466 /* The most likely cause for this is that we destroyed the monitor in the
1467 * time between subscribing to its device state and the time this executes.
1468 * Not really a big deal.
1469 */
1470 return 0;
1471 }
1472
1473 if (generic_list->current_state == new_state) {
1474 /* The device state hasn't actually changed, so we don't really care */
1475 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1476 return 0;
1477 }
1478
1479 previous_state = generic_list->current_state;
1480 generic_list->current_state = new_state;
1481
1482 if (cc_generic_is_device_available(new_state) &&
1483 (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE ||
1484 previous_state == AST_DEVICE_BUSY)) {
1485 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1486 if (!generic_instance->is_suspended && generic_instance->monitoring) {
1487 generic_instance->monitoring = 0;
1488 generic_list->fit_for_recall = 1;
1489 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1490 break;
1491 }
1492 }
1493 }
1494 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1495 return 0;
1496}
@ AST_DEVICE_INUSE
Definition devicestate.h:55
@ AST_DEVICE_BUSY
Definition devicestate.h:56
@ AST_DEVICE_UNAVAILABLE
Definition devicestate.h:58
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

References ao2_cleanup, ast_cc_monitor_callee_available(), AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_UNAVAILABLE, AST_LIST_TRAVERSE, cc_generic_is_device_available(), cc_unref(), generic_monitor_instance::core_id, generic_monitor_instance_list::current_state, find_generic_monitor_instance_list(), generic_monitor_instance_list::fit_for_recall, generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, generic_monitor_instance::monitoring, generic_monitor_instance::next, and RAII_VAR.

Referenced by generic_monitor_devstate_cb().

◆ generic_monitor_instance_list_destructor()

static void generic_monitor_instance_list_destructor ( void *  obj)
static

Definition at line 1410 of file ccss.c.

1411{
1412 struct generic_monitor_instance_list *generic_list = obj;
1413 struct generic_monitor_instance *generic_instance;
1414
1415 generic_list->sub = stasis_unsubscribe(generic_list->sub);
1416 while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) {
1417 ast_free(generic_instance);
1418 }
1419 ast_free((char *)generic_list->device_name);
1420}

References ast_free, AST_LIST_REMOVE_HEAD, generic_monitor_instance_list::device_name, generic_monitor_instance_list::list, generic_monitor_instance::next, stasis_unsubscribe(), and generic_monitor_instance_list::sub.

Referenced by create_new_generic_list().

◆ generic_recall()

static void * generic_recall ( void *  data)
static

Definition at line 2845 of file ccss.c.

2846{
2847 struct ast_cc_agent *agent = data;
2848 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2849 const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name));
2850 const char *tech;
2851 char *target;
2852 int reason;
2853 struct ast_channel *chan;
2854 const char *callback_sub = ast_get_cc_callback_sub(agent->cc_params);
2855 unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
2857
2858 if (!tmp_cap) {
2859 return NULL;
2860 }
2861
2862 tech = interface;
2863 if ((target = strchr(interface, '/'))) {
2864 *target++ = '\0';
2865 }
2866
2868 if (!(chan = ast_request_and_dial(tech, tmp_cap, NULL, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
2869 /* Hmm, no channel. Sucks for you, bud.
2870 */
2871 ast_log_dynamic_level(cc_logger_level, "Core %u: Failed to call back %s for reason %d\n",
2872 agent->core_id, agent->device_name, reason);
2873 ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target);
2874 ao2_ref(tmp_cap, -1);
2875 return NULL;
2876 }
2877 ao2_ref(tmp_cap, -1);
2878
2879 /* We have a channel. It's time now to set up the datastore of recalled CC interfaces.
2880 * This will be a common task for all recall functions. If it were possible, I'd have
2881 * the core do it automatically, but alas I cannot. Instead, I will provide a public
2882 * function to do so.
2883 */
2886
2887 ast_channel_exten_set(chan, generic_pvt->exten);
2888 ast_channel_context_set(chan, generic_pvt->context);
2889 ast_channel_priority_set(chan, 1);
2890
2891 pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten);
2892 pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context);
2893
2894 if (!ast_strlen_zero(callback_sub)) {
2895 ast_log_dynamic_level(cc_logger_level, "Core %u: There's a callback subroutine configured for agent %s\n",
2896 agent->core_id, agent->device_name);
2897 if (ast_app_exec_sub(NULL, chan, callback_sub, 0)) {
2898 ast_cc_failed(agent->core_id, "Callback subroutine to %s failed. Maybe a hangup?", agent->device_name);
2899 ast_hangup(chan);
2900 return NULL;
2901 }
2902 }
2903 if (ast_pbx_start(chan)) {
2904 ast_cc_failed(agent->core_id, "PBX failed to start for %s.", agent->device_name);
2905 ast_hangup(chan);
2906 return NULL;
2907 }
2908 ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling",
2909 agent->device_name);
2910 return NULL;
2911}
int ast_setup_cc_recall_datastore(struct ast_channel *chan, const int core_id)
Set up a CC recall datastore on a channel.
Definition ccss.c:3423
int ast_cc_agent_recalling(int core_id, const char *const debug,...)
Tell the CC core that a caller is currently recalling.
Definition ccss.c:3872
int ast_cc_agent_set_interfaces_chanvar(struct ast_channel *chan)
Set the first level CC_INTERFACES channel variable for a channel.
Definition ccss.c:3654
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2538
struct ast_channel * ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int timeout, int *reason, const char *cid_num, const char *cid_name)
Request a channel of a given type, with data as optional information used by the low level module and...
Definition channel.c:6169
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition format_cap.h:49
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition main/app.c:297
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition pbx.c:4729
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54

References ao2_ref, ast_app_exec_sub(), ast_cc_agent_recalling(), ast_cc_agent_set_interfaces_chanvar(), ast_cc_failed(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_priority_set(), ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_get_cc_agent_dialstring(), ast_get_cc_callback_sub(), ast_get_cc_recall_timer(), ast_hangup(), ast_log_dynamic_level, ast_pbx_start(), ast_request_and_dial(), ast_setup_cc_recall_datastore(), ast_strdupa, ast_strlen_zero(), cc_logger_level, ast_cc_agent::cc_params, cc_generic_agent_pvt::cid_name, cc_generic_agent_pvt::cid_num, cc_generic_agent_pvt::context, ast_cc_agent::core_id, ast_cc_agent::device_name, cc_generic_agent_pvt::exten, NULL, pbx_builtin_setvar_helper(), ast_cc_agent::private_data, and S_OR.

Referenced by cc_generic_agent_recall().

◆ handle_cc_kill()

static char * handle_cc_kill ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4661 of file ccss.c.

4662{
4663 switch (cmd) {
4664 case CLI_INIT:
4665 e->command = "cc cancel [core|all]";
4666 e->usage =
4667 "Usage: cc cancel can be used in two ways.\n"
4668 " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n"
4669 " core ID equal to the specified core ID.\n"
4670 " 2. 'cc cancel all' will cancel all active CC transactions.\n";
4671 return NULL;
4672 case CLI_GENERATE:
4673 if (a->pos == 3 && !strcasecmp(a->argv[2], "core")) {
4674 return complete_core_id(a->word);
4675 }
4676 return NULL;
4677 }
4678
4679 if (a->argc == 4) {
4680 int core_id;
4681 char *endptr;
4682 if (strcasecmp(a->argv[2], "core")) {
4683 return CLI_SHOWUSAGE;
4684 }
4685 core_id = strtol(a->argv[3], &endptr, 10);
4686 if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) {
4687 return CLI_SHOWUSAGE;
4688 }
4689 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id");
4690 } else if (a->argc == 3) {
4691 if (strcasecmp(a->argv[2], "all")) {
4692 return CLI_SHOWUSAGE;
4693 }
4694 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores");
4695 } else {
4696 return CLI_SHOWUSAGE;
4697 }
4698
4699 return CLI_SUCCESS;
4700}
static int kill_cores(void *obj, void *arg, int flags)
Definition ccss.c:4628
static char * complete_core_id(const char *word)
Definition ccss.c:4639
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
int errno
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
static struct test_val a

References a, ao2_t_callback, cc_core_instances, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_id(), cc_core_instance::core_id, errno, kill_cores(), NULL, OBJ_NODATA, and ast_cli_entry::usage.

◆ handle_cc_status()

static char * handle_cc_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4595 of file ccss.c.

4596{
4597 int *cli_fd;
4598
4599 switch (cmd) {
4600 case CLI_INIT:
4601 e->command = "cc report status";
4602 e->usage =
4603 "Usage: cc report status\n"
4604 " Report the current status of any ongoing CC transactions\n";
4605 return NULL;
4606 case CLI_GENERATE:
4607 return NULL;
4608 }
4609
4610 if (a->argc != 3) {
4611 return CLI_SHOWUSAGE;
4612 }
4613
4614 cli_fd = ast_malloc(sizeof(*cli_fd));
4615 if (!cli_fd) {
4616 return CLI_FAILURE;
4617 }
4618
4619 *cli_fd = a->fd;
4620
4622 ast_free(cli_fd);
4623 return CLI_FAILURE;
4624 }
4625 return CLI_SUCCESS;
4626}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
static int cc_cli_output_status(void *data)
Definition ccss.c:4578
#define CLI_FAILURE
Definition cli.h:46

References a, ast_free, ast_malloc, ast_taskprocessor_push(), cc_cli_output_status(), cc_core_taskprocessor, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ has_device_monitors()

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

3112{
3113 struct ast_cc_monitor *iter;
3114 int res = 0;
3115
3116 AST_LIST_TRAVERSE(core_instance->monitors, iter, next) {
3118 res = 1;
3119 break;
3120 }
3121 }
3122
3123 return res;
3124}

References AST_CC_DEVICE_MONITOR, AST_LIST_TRAVERSE, ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, and ast_cc_monitor::next.

Referenced by cancel_available_timer(), cc_monitor_failed(), request_cc(), suspend(), and unsuspend().

◆ initialize_cc_devstate_map()

static void initialize_cc_devstate_map ( struct ast_config cc_config)
static

Definition at line 4497 of file ccss.c.

4498{
4499 initialize_cc_devstate_map_helper(cc_config, CC_AVAILABLE, "cc_available_devstate");
4500 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_OFFERED, "cc_caller_offered_devstate");
4501 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_REQUESTED, "cc_caller_requested_devstate");
4502 initialize_cc_devstate_map_helper(cc_config, CC_ACTIVE, "cc_active_devstate");
4503 initialize_cc_devstate_map_helper(cc_config, CC_CALLEE_READY, "cc_callee_ready_devstate");
4504 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_BUSY, "cc_caller_busy_devstate");
4505 initialize_cc_devstate_map_helper(cc_config, CC_RECALLING, "cc_recalling_devstate");
4506 initialize_cc_devstate_map_helper(cc_config, CC_COMPLETE, "cc_complete_devstate");
4507 initialize_cc_devstate_map_helper(cc_config, CC_FAILED, "cc_failed_devstate");
4508
4509}
static void initialize_cc_devstate_map_helper(struct ast_config *cc_config, enum cc_state state, const char *cc_setting)
Definition ccss.c:4473

References CC_ACTIVE, CC_AVAILABLE, CC_CALLEE_READY, CC_CALLER_BUSY, CC_CALLER_OFFERED, CC_CALLER_REQUESTED, CC_COMPLETE, CC_FAILED, CC_RECALLING, and initialize_cc_devstate_map_helper().

Referenced by load_config().

◆ initialize_cc_devstate_map_helper()

static void initialize_cc_devstate_map_helper ( struct ast_config cc_config,
enum cc_state  state,
const char *  cc_setting 
)
static

Definition at line 4473 of file ccss.c.

4474{
4475 const char *cc_devstate_str;
4476 enum ast_device_state this_devstate;
4477
4478 if ((cc_devstate_str = ast_variable_retrieve(cc_config, "general", cc_setting))) {
4479 this_devstate = ast_devstate_val(cc_devstate_str);
4480 if (this_devstate != AST_DEVICE_UNKNOWN) {
4481 cc_state_to_devstate_map[state] = this_devstate;
4482 }
4483 }
4484}
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)

References AST_DEVICE_UNKNOWN, ast_devstate_val(), ast_variable_retrieve(), cc_state_to_devstate_map, and state.

Referenced by initialize_cc_devstate_map().

◆ initialize_cc_max_requests()

static void initialize_cc_max_requests ( struct ast_config cc_config)
static

Definition at line 4449 of file ccss.c.

4450{
4451 const char *cc_max_requests_str;
4452 char *endptr;
4453
4454 if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) {
4456 return;
4457 }
4458
4459 global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10);
4460
4461 if (!ast_strlen_zero(endptr)) {
4462 ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n");
4464 }
4465
4466 return;
4467}
#define GLOBAL_CC_MAX_REQUESTS_DEFAULT
Definition ccss.c:679

References ast_log, ast_strlen_zero(), ast_variable_retrieve(), global_cc_max_requests, GLOBAL_CC_MAX_REQUESTS_DEFAULT, and LOG_WARNING.

Referenced by load_config().

◆ is_state_change_valid()

static int is_state_change_valid ( enum cc_state  current_state,
const enum cc_state  new_state,
struct ast_cc_agent agent 
)
static

Definition at line 3019 of file ccss.c.

3020{
3021 int is_valid = 0;
3022 switch (new_state) {
3023 case CC_AVAILABLE:
3024 ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to state %u? That should never happen.\n",
3025 agent->core_id, new_state);
3026 break;
3027 case CC_CALLER_OFFERED:
3028 if (current_state == CC_AVAILABLE) {
3029 is_valid = 1;
3030 }
3031 break;
3033 if (current_state == CC_CALLER_OFFERED ||
3034 (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) {
3035 is_valid = 1;
3036 }
3037 break;
3038 case CC_ACTIVE:
3039 if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) {
3040 is_valid = 1;
3041 }
3042 break;
3043 case CC_CALLEE_READY:
3044 if (current_state == CC_ACTIVE) {
3045 is_valid = 1;
3046 }
3047 break;
3048 case CC_CALLER_BUSY:
3049 if (current_state == CC_CALLEE_READY) {
3050 is_valid = 1;
3051 }
3052 break;
3053 case CC_RECALLING:
3054 if (current_state == CC_CALLEE_READY) {
3055 is_valid = 1;
3056 }
3057 break;
3058 case CC_COMPLETE:
3059 if (current_state == CC_RECALLING) {
3060 is_valid = 1;
3061 }
3062 break;
3063 case CC_FAILED:
3064 is_valid = 1;
3065 break;
3066 default:
3067 ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to unknown state %u\n",
3068 agent->core_id, new_state);
3069 break;
3070 }
3071
3072 return is_valid;
3073}
#define ast_test_flag(p, flag)
Definition utils.h:64

References cc_core_instance::agent, AST_CC_AGENT_SKIP_OFFER, ast_log_dynamic_level, ast_test_flag, CC_ACTIVE, CC_AVAILABLE, CC_CALLEE_READY, CC_CALLER_BUSY, CC_CALLER_OFFERED, CC_CALLER_REQUESTED, CC_COMPLETE, CC_FAILED, cc_logger_level, CC_RECALLING, ast_cc_agent::core_id, and cc_core_instance::current_state.

Referenced by cc_do_state_change().

◆ kill_cores()

static int kill_cores ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 4628 of file ccss.c.

4629{
4630 int *core_id = arg;
4631 struct cc_core_instance *core_instance = obj;
4632
4633 if (!core_id || (core_instance->core_id == *core_id)) {
4634 ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n");
4635 }
4636 return 0;
4637}

References ast_cc_failed(), and cc_core_instance::core_id.

Referenced by handle_cc_kill().

◆ kill_duplicate_offers()

static void kill_duplicate_offers ( char *  caller)
static

Definition at line 2544 of file ccss.c.

2545{
2546 unsigned long match_flags = MATCH_NO_REQUEST;
2547 struct ao2_iterator *dups_iter;
2548
2549 /*
2550 * Must remove the ref that was in cc_core_instances outside of
2551 * the container lock to prevent deadlock.
2552 */
2554 match_agent, caller, &match_flags, "Killing duplicate offers");
2555 if (dups_iter) {
2556 /* Now actually unref any duplicate offers by simply destroying the iterator. */
2557 ao2_iterator_destroy(dups_iter);
2558 }
2559}
@ OBJ_MULTIPLE
Definition astobj2.h:1049
@ OBJ_UNLINK
Definition astobj2.h:1039

References ao2_iterator_destroy(), ao2_t_callback_data, cc_core_instances, match_agent(), MATCH_NO_REQUEST, OBJ_MULTIPLE, and OBJ_UNLINK.

Referenced by cc_core_init_instance().

◆ load_config()

static int load_config ( void  )
static

Definition at line 4511 of file ccss.c.

4512{
4513 struct ast_flags config_flags = { 0, };
4514 const char *enabled = NULL;
4515 struct ast_config *cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
4516
4517 global_enabled = 1;
4518
4519 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
4520 ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests and devstate defaults\n");
4522 return 0;
4523 }
4524
4525 if ((enabled = ast_variable_retrieve(cc_config, "general", "enabled"))) {
4527 }
4528
4529 if (global_enabled) {
4530 initialize_cc_max_requests(cc_config);
4531 initialize_cc_devstate_map(cc_config);
4532 } else {
4533 ast_log(LOG_NOTICE, "CCSS disabled globally\n");
4534 }
4535 ast_config_destroy(cc_config);
4536
4537 return !global_enabled;
4538}
static void initialize_cc_devstate_map(struct ast_config *cc_config)
Definition ccss.c:4497
static void initialize_cc_max_requests(struct ast_config *cc_config)
Definition ccss.c:4449
static int enabled
Definition dnsmgr.c:91
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition utils.c:2235
Structure used to handle boolean flags.
Definition utils.h:220

References ast_config_destroy(), ast_config_load2(), ast_log, ast_true(), ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, enabled, global_cc_max_requests, GLOBAL_CC_MAX_REQUESTS_DEFAULT, global_enabled, initialize_cc_devstate_map(), initialize_cc_max_requests(), LOG_NOTICE, LOG_WARNING, and NULL.

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 4741 of file ccss.c.

4742{
4743 int res;
4744
4745 res = load_config();
4746 if (res != 0) {
4748 }
4749
4753 "Create core instance container");
4754 if (!cc_core_instances) {
4756 }
4757
4760 generic_monitor_instance_list_hash_fn, NULL, generic_monitor_instance_list_cmp_fn,
4761 "Create generic monitor container");
4762 if (!generic_monitors) {
4764 }
4767 }
4770 }
4773 }
4778
4783
4785}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition astobj2.h:363
#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag)
Definition astobj2.h:1306
static enum ast_device_state ccss_device_state(const char *device_name)
Definition ccss.c:619
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition ccss.c:1186
static const int CC_CORE_INSTANCES_BUCKETS
Definition ccss.c:341
static const char * ccreq_app
Definition ccss.c:4325
static int cccancel_exec(struct ast_channel *chan, const char *data)
Definition ccss.c:4378
static const char * cccancel_app
Definition ccss.c:4376
static int cc_core_instance_cmp_fn(void *obj, void *arg, int flags)
Definition ccss.c:439
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition ccss.c:1247
static const char * CC_LOGGER_LEVEL_NAME
Definition ccss.c:145
static struct ast_cc_monitor_callbacks generic_monitor_cbs
Definition ccss.c:1338
static int ccreq_exec(struct ast_channel *chan, const char *data)
Definition ccss.c:4327
static struct ast_cli_entry cc_cli[]
Definition ccss.c:4702
static int load_config(void)
Definition ccss.c:4511
static int cc_core_instance_hash_fn(const void *obj, const int flags)
Definition ccss.c:433
static struct ast_cc_agent_callbacks generic_agent_callbacks
Definition ccss.c:2635
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition logger.c:2821
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition pbx_app.c:104
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition sched.c:197
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition sched.c:238
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary.
@ TPS_REF_DEFAULT
return a reference to a taskprocessor, create one if it does not exist
#define ARRAY_LEN(a)
Definition utils.h:706

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_t_container_alloc_hash, ARRAY_LEN, ast_cc_agent_register(), ast_cc_monitor_register(), ast_cli_register_multiple, ast_devstate_prov_add(), ast_logger_register_level(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application2(), ast_sched_context_create(), ast_sched_start_thread(), ast_taskprocessor_get(), cc_cli, cc_core_instance_cmp_fn(), cc_core_instance_hash_fn(), cc_core_instances, CC_CORE_INSTANCES_BUCKETS, cc_core_taskprocessor, cc_logger_level, CC_LOGGER_LEVEL_NAME, cc_sched_context, cccancel_app, cccancel_exec(), ccreq_app, ccreq_exec(), ccss_device_state(), dialed_cc_interface_counter, generic_agent_callbacks, generic_monitor_cbs, generic_monitors, load_config(), NULL, and TPS_REF_DEFAULT.

◆ match_agent()

static int match_agent ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 511 of file ccss.c.

512{
513 struct cc_core_instance *core_instance = obj;
514 const char *name = arg;
515 unsigned long match_flags = *(unsigned long *)data;
516 int possible_match = 0;
517
519 possible_match = 1;
520 }
521
522 if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) {
523 possible_match = 1;
524 }
525
526 if (!possible_match) {
527 return 0;
528 }
529
530 if (!strcmp(core_instance->agent->device_name, name)) {
531 return CMP_MATCH | CMP_STOP;
532 }
533 return 0;
534}

References cc_core_instance::agent, CC_CALLER_REQUESTED, CMP_MATCH, CMP_STOP, cc_core_instance::current_state, ast_cc_agent::device_name, MATCH_NO_REQUEST, MATCH_REQUEST, and name.

Referenced by cccancel_exec(), ccreq_exec(), ccss_device_state(), and kill_duplicate_offers().

◆ monitor_policy_to_str()

static const char * monitor_policy_to_str ( enum ast_cc_monitor_policies  policy)
static

Definition at line 764 of file ccss.c.

765{
766 switch (policy) {
768 return "never";
770 return "native";
772 return "generic";
774 return "always";
775 default:
776 /* This should never happen... */
777 return "";
778 }
779}
@ AST_CC_MONITOR_NEVER
Definition ccss.h:76
@ AST_CC_MONITOR_NATIVE
Definition ccss.h:78

References AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, and AST_CC_MONITOR_NEVER.

Referenced by ast_cc_get_param().

◆ offer_timer_expire()

static int offer_timer_expire ( const void *  data)
static

Definition at line 2720 of file ccss.c.

2721{
2722 struct ast_cc_agent *agent = (struct ast_cc_agent *) data;
2724 ast_log_dynamic_level(cc_logger_level, "Core %u: Queuing change request because offer timer has expired.\n",
2725 agent->core_id);
2726 agent_pvt->offer_timer_id = -1;
2727 ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name);
2728 cc_unref(agent, "Remove scheduler's reference to the agent");
2729 return 0;
2730}

References ast_cc_failed(), ast_log_dynamic_level, cc_logger_level, cc_unref(), ast_cc_agent::core_id, ast_cc_agent::device_name, and ast_cc_agent::private_data.

Referenced by cc_generic_agent_start_offer_timer().

◆ print_stats_cb()

static int print_stats_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 4565 of file ccss.c.

4566{
4567 int *cli_fd = arg;
4568 struct cc_core_instance *core_instance = obj;
4569
4570 ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name,
4571 cc_state_to_string(core_instance->current_state));
4572 AST_LIST_LOCK(core_instance->monitors);
4573 cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0);
4574 AST_LIST_UNLOCK(core_instance->monitors);
4575 return 0;
4576}

References cc_core_instance::agent, ast_cli(), AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, cc_cli_print_monitor_stats(), cc_state_to_string(), cc_core_instance::core_id, cc_core_instance::current_state, ast_cc_agent::device_name, and cc_core_instance::monitors.

Referenced by cc_cli_output_status().

◆ request_cc()

static void request_cc ( struct cc_core_instance core_instance)
static

Definition at line 3126 of file ccss.c.

3127{
3128 struct ast_cc_monitor *monitor_iter;
3129 AST_LIST_LOCK(core_instance->monitors);
3130 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3131 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3132 if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) {
3134 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3135 monitor_iter->interface->device_name, 1);
3136 cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor");
3137 } else {
3138 cc_publish_requested(core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name);
3139 }
3140 }
3141 }
3143
3144 if (!has_device_monitors(core_instance)) {
3145 ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC");
3146 }
3147 AST_LIST_UNLOCK(core_instance->monitors);
3148}
static void cc_publish_requested(int core_id, const char *caller, const char *callee)
Definition ccss.c:1089
int(* request_cc)(struct ast_cc_monitor *monitor, int *available_timer_id)
Request CCSS.
Definition ccss.h:565

References cc_core_instance::agent, AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_publish_requested(), cc_unref(), cc_core_instance::core_id, ast_cc_interface::device_name, ast_cc_agent::device_name, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, ast_cc_monitor::next, ast_cc_monitor::parent_id, and ast_cc_monitor_callbacks::request_cc.

Referenced by cc_caller_requested().

◆ str_to_agent_policy()

static enum ast_cc_agent_policies str_to_agent_policy ( const char *const  value)
static

Definition at line 719 of file ccss.c.

720{
721 if (!strcasecmp(value, "never")) {
722 return AST_CC_AGENT_NEVER;
723 } else if (!strcasecmp(value, "native")) {
724 return AST_CC_AGENT_NATIVE;
725 } else if (!strcasecmp(value, "generic")) {
727 } else {
728 ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value);
729 return AST_CC_AGENT_NEVER;
730 }
731}

References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, AST_CC_AGENT_NEVER, ast_log, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

◆ str_to_monitor_policy()

static enum ast_cc_monitor_policies str_to_monitor_policy ( const char *const  value)
static

Definition at line 733 of file ccss.c.

734{
735 if (!strcasecmp(value, "never")) {
737 } else if (!strcasecmp(value, "native")) {
739 } else if (!strcasecmp(value, "generic")) {
741 } else if (!strcasecmp(value, "always")) {
743 } else {
744 ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value);
746 }
747}

References AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, ast_log, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

◆ suspend()

static void suspend ( struct cc_core_instance core_instance)
static

Definition at line 3211 of file ccss.c.

3212{
3213 struct ast_cc_monitor *monitor_iter;
3214 AST_LIST_LOCK(core_instance->monitors);
3215 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3216 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3217 if (monitor_iter->callbacks->suspend(monitor_iter)) {
3219 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3220 monitor_iter->interface->device_name, 1);
3221 cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor");
3222 }
3223 }
3224 }
3226
3227 if (!has_device_monitors(core_instance)) {
3228 ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC");
3229 }
3230 AST_LIST_UNLOCK(core_instance->monitors);
3231}
int(* suspend)(struct ast_cc_monitor *monitor)
Suspend monitoring.
Definition ccss.h:578

References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, ast_cc_interface::device_name, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, ast_cc_monitor::next, ast_cc_monitor::parent_id, and ast_cc_monitor_callbacks::suspend.

Referenced by ast_control_streamfile(), ast_control_streamfile_lang(), ast_control_streamfile_w_cb(), cc_caller_busy(), control_streamfile(), handle_bridge_technology_suspend(), handle_controlstreamfile(), and handle_manager_bridge_tech_suspend().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 4707 of file ccss.c.

4708{
4709 if (!global_enabled) {
4710 return 0;
4711 }
4712
4713 ast_devstate_prov_del("ccss");
4720
4721 if (cc_sched_context) {
4724 }
4727 }
4728 /* Note that core instances must be destroyed prior to the generic_monitors */
4729 if (cc_core_instances) {
4730 ao2_t_ref(cc_core_instances, -1, "Unref cc_core_instances container in cc_shutdown");
4732 }
4733 if (generic_monitors) {
4734 ao2_t_ref(generic_monitors, -1, "Unref generic_monitor container in cc_shutdown");
4736 }
4737
4738 return 0;
4739}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition ccss.c:1222
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition ccss.c:1265
int ast_devstate_prov_del(const char *label)
Remove device state provider.
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition logger.c:2879
int ast_unregister_application(const char *app)
Unregister an application.
Definition pbx_app.c:392
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition sched.c:271
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.

References ao2_t_ref, ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_cli_unregister_multiple(), ast_devstate_prov_del(), ast_logger_unregister_level(), ast_sched_context_destroy(), ast_taskprocessor_unreference(), ast_unregister_application(), cc_cli, cc_core_instances, cc_core_taskprocessor, CC_LOGGER_LEVEL_NAME, cc_sched_context, cccancel_app, ccreq_app, generic_agent_callbacks, generic_monitor_cbs, generic_monitors, global_enabled, and NULL.

◆ unsuspend()

static void unsuspend ( struct cc_core_instance core_instance)
static

Definition at line 3164 of file ccss.c.

3165{
3166 struct ast_cc_monitor *monitor_iter;
3167 AST_LIST_LOCK(core_instance->monitors);
3168 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3169 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3170 if (monitor_iter->callbacks->unsuspend(monitor_iter)) {
3172 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3173 monitor_iter->interface->device_name, 1);
3174 cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor");
3175 }
3176 }
3177 }
3179
3180 if (!has_device_monitors(core_instance)) {
3181 ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC");
3182 }
3183 AST_LIST_UNLOCK(core_instance->monitors);
3184}
int(* unsuspend)(struct ast_cc_monitor *monitor)
Unsuspend monitoring.
Definition ccss.h:606

References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, ast_cc_interface::device_name, has_device_monitors(), ast_cc_monitor::interface, ast_cc_interface::monitor_class, cc_core_instance::monitors, ast_cc_monitor::next, ast_cc_monitor::parent_id, and ast_cc_monitor_callbacks::unsuspend.

Referenced by cc_active().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Call Completion Supplementary Services" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CORE, }
static

Definition at line 4792 of file ccss.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4792 of file ccss.c.

◆ cc_agent_backends

◆ cc_cli

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" ,},
}
static char * handle_cc_kill(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition ccss.c:4661
static char * handle_cc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition ccss.c:4595

Definition at line 4702 of file ccss.c.

4702 {
4703 AST_CLI_DEFINE(handle_cc_status, "Reports CC stats"),
4704 AST_CLI_DEFINE(handle_cc_kill, "Kill a CC transaction"),
4705};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by load_module(), and unload_module().

◆ cc_core_instances

struct ao2_container* cc_core_instances
static

◆ CC_CORE_INSTANCES_BUCKETS

const int CC_CORE_INSTANCES_BUCKETS = 17
static

Definition at line 341 of file ccss.c.

Referenced by load_module().

◆ cc_core_taskprocessor

struct ast_taskprocessor* cc_core_taskprocessor
static

◆ cc_default_params

const struct ast_cc_config_params cc_default_params
static

Definition at line 681 of file ccss.c.

681 {
682 .cc_agent_policy = AST_CC_AGENT_NEVER,
683 .cc_monitor_policy = AST_CC_MONITOR_NEVER,
684 .cc_offer_timer = CC_OFFER_TIMER_DEFAULT,
685 .ccnr_available_timer = CCNR_AVAILABLE_TIMER_DEFAULT,
686 .ccbs_available_timer = CCBS_AVAILABLE_TIMER_DEFAULT,
687 .cc_recall_timer = CC_RECALL_TIMER_DEFAULT,
688 .cc_max_agents = CC_MAX_AGENTS_DEFAULT,
689 .cc_max_monitors = CC_MAX_MONITORS_DEFAULT,
690 .cc_callback_sub = "",
691 .cc_agent_dialstring = "",
692};
#define CC_OFFER_TIMER_DEFAULT
Definition ccss.c:673
#define CCNR_AVAILABLE_TIMER_DEFAULT
Definition ccss.c:674
#define CC_MAX_AGENTS_DEFAULT
Definition ccss.c:677
#define CCBS_AVAILABLE_TIMER_DEFAULT
Definition ccss.c:675
#define CC_RECALL_TIMER_DEFAULT
Definition ccss.c:676
#define CC_MAX_MONITORS_DEFAULT
Definition ccss.c:678

Referenced by ast_cc_default_config_params().

◆ cc_logger_level

int cc_logger_level
static

◆ CC_LOGGER_LEVEL_NAME

const char* CC_LOGGER_LEVEL_NAME = "CC"
static

Name printed on all CC log messages.

Definition at line 145 of file ccss.c.

Referenced by load_module(), and unload_module().

◆ cc_monitor_backends

◆ cc_request_count

int cc_request_count
static

The current number of CC requests in the system

Definition at line 157 of file ccss.c.

Referenced by ast_cc_request_is_within_limits().

◆ cc_sched_context

struct ast_sched_context* cc_sched_context
static

◆ [struct]

const struct { ... } cc_service_to_string_map[]

Referenced by cc_service_to_string().

◆ cc_state_to_devstate_map

enum ast_device_state cc_state_to_devstate_map[]
static

Definition at line 582 of file ccss.c.

582 {
592};
#define CC_CALLER_REQUESTED_DEVSTATE_DEFAULT
Definition ccss.c:570
#define CC_FAILED_DEVSTATE_DEFAULT
Definition ccss.c:576
#define CC_COMPLETE_DEVSTATE_DEFAULT
Definition ccss.c:575
#define CC_AVAILABLE_DEVSTATE_DEFAULT
Definition ccss.c:568
#define CC_CALLER_BUSY_DEVSTATE_DEFAULT
Definition ccss.c:573
#define CC_CALLEE_READY_DEVSTATE_DEFAULT
Definition ccss.c:572
#define CC_CALLER_OFFERED_DEVSTATE_DEFAULT
Definition ccss.c:569
#define CC_RECALLING_DEVSTATE_DEFAULT
Definition ccss.c:574
#define CC_ACTIVE_DEVSTATE_DEFAULT
Definition ccss.c:571

Referenced by cc_state_to_devstate(), and initialize_cc_devstate_map_helper().

◆ [struct]

const struct { ... } cc_state_to_string_map[]

Referenced by cc_state_to_string().

◆ cccancel_app

const char* cccancel_app = "CallCompletionCancel"
static

Definition at line 4376 of file ccss.c.

Referenced by load_module(), and unload_module().

◆ ccreq_app

const char* ccreq_app = "CallCompletionRequest"
static

Definition at line 4325 of file ccss.c.

Referenced by load_module(), and unload_module().

◆ core_id_counter

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

Referenced by cc_interfaces_datastore_init().

◆ dialed_cc_interface_counter

int dialed_cc_interface_counter
static

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

Definition at line 1892 of file ccss.c.

Referenced by cc_device_monitor_init(), cc_extension_monitor_init(), and load_module().

◆ dialed_cc_interfaces_info

const struct ast_datastore_info dialed_cc_interfaces_info
static
Initial value:
= {
.type = "Dial CC Interfaces",
}
static void dialed_cc_interfaces_destroy(void *data)
Definition ccss.c:1961
static void * dialed_cc_interfaces_duplicate(void *data)
Definition ccss.c:1981

Definition at line 2006 of file ccss.c.

2006 {
2007 .type = "Dial CC Interfaces",
2008 .duplicate = dialed_cc_interfaces_duplicate,
2010};

Referenced by ast_cc_call_init(), ast_cc_extension_monitor_add_dialstring(), ast_cc_get_current_core_id(), ast_cc_offer(), ast_handle_cc_control_frame(), ast_ignore_cc(), cc_build_payload(), and cc_interfaces_datastore_init().

◆ generic_agent_callbacks

struct ast_cc_agent_callbacks generic_agent_callbacks
static

Definition at line 2635 of file ccss.c.

2635 {
2636 .type = "generic",
2637 .init = cc_generic_agent_init,
2638 .start_offer_timer = cc_generic_agent_start_offer_timer,
2639 .stop_offer_timer = cc_generic_agent_stop_offer_timer,
2640 .respond = cc_generic_agent_respond,
2641 .status_request = cc_generic_agent_status_request,
2642 .stop_ringing = cc_generic_agent_stop_ringing,
2643 .start_monitoring = cc_generic_agent_start_monitoring,
2644 .callee_available = cc_generic_agent_recall,
2645 .destructor = cc_generic_agent_destructor,
2646};
static void cc_generic_agent_respond(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Definition ccss.c:2764
static int cc_generic_agent_recall(struct ast_cc_agent *agent)
Definition ccss.c:2913
static int cc_generic_agent_stop_ringing(struct ast_cc_agent *agent)
Definition ccss.c:2778
static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
Definition ccss.c:2698
static void cc_generic_agent_destructor(struct ast_cc_agent *agent)
Definition ccss.c:2929
static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent)
Definition ccss.c:2820
static int cc_generic_agent_status_request(struct ast_cc_agent *agent)
Definition ccss.c:2772
static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent)
Definition ccss.c:2732

Referenced by load_module(), and unload_module().

◆ generic_monitor_cbs

struct ast_cc_monitor_callbacks generic_monitor_cbs
static

Definition at line 1338 of file ccss.c.

1338 {
1339 .type = "generic",
1340 .request_cc = cc_generic_monitor_request_cc,
1341 .suspend = cc_generic_monitor_suspend,
1342 .unsuspend = cc_generic_monitor_unsuspend,
1343 .cancel_available_timer = cc_generic_monitor_cancel_available_timer,
1344 .destructor = cc_generic_monitor_destructor,
1345};
static int cc_generic_monitor_unsuspend(struct ast_cc_monitor *monitor)
Definition ccss.c:1640
static int cc_generic_monitor_cancel_available_timer(struct ast_cc_monitor *monitor, int *sched_id)
Definition ccss.c:1668
static int cc_generic_monitor_suspend(struct ast_cc_monitor *monitor)
Definition ccss.c:1599
static int cc_generic_monitor_request_cc(struct ast_cc_monitor *monitor, int *available_timer_id)
Definition ccss.c:1536
static void cc_generic_monitor_destructor(void *private_data)
Definition ccss.c:1685

Referenced by load_module(), and unload_module().

◆ generic_monitors

struct ao2_container* generic_monitors

◆ global_cc_max_requests

unsigned int global_cc_max_requests
static

Parsed configuration value for cc_max_requests

Definition at line 153 of file ccss.c.

Referenced by ast_cc_request_is_within_limits(), initialize_cc_max_requests(), and load_config().

◆ global_enabled

int global_enabled
static

Definition at line 118 of file ccss.c.

Referenced by ast_cc_call_init(), ast_cc_is_enabled(), load_config(), and unload_module().

◆ recall_ds_info

const struct ast_datastore_info recall_ds_info
static
Initial value:
= {
.type = "cc_recall",
.duplicate = cc_recall_ds_duplicate,
}
static void cc_recall_ds_destroy(void *data)
Definition ccss.c:3410
static void * cc_recall_ds_duplicate(void *data)
Definition ccss.c:3396

Definition at line 3417 of file ccss.c.

3417 {
3418 .type = "cc_recall",
3419 .duplicate = cc_recall_ds_duplicate,
3420 .destroy = cc_recall_ds_destroy,
3421};

Referenced by ast_cc_agent_set_interfaces_chanvar(), ast_cc_completed(), ast_cc_is_recall(), ast_ignore_cc(), ast_set_cc_interfaces_chanvar(), and ast_setup_cc_recall_datastore().

◆ service

enum ast_cc_service_type service

◆ service_string

const char* service_string

Definition at line 400 of file ccss.c.

◆ state

◆ state_change_funcs

int(*const state_change_funcs[])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state) ( struct cc_core_instance ,
struct cc_state_change_args ,
enum cc_state  previous_state 
)
static

Definition at line 3291 of file ccss.c.

3291 {
3295 [CC_ACTIVE] = cc_active,
3300 [CC_FAILED] = cc_failed,
3301};
static int cc_complete(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3275
static int cc_recalling(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3266
static int cc_caller_offered(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3082
static int cc_caller_requested(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3150
static int cc_callee_ready(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3205
static int cc_failed(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3284
static int cc_caller_busy(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3233
static int cc_active(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3186
static int cc_available(struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
Definition ccss.c:3075

Referenced by cc_do_state_change().

◆ state_string

const char* state_string

Definition at line 410 of file ccss.c.