Asterisk - The Open Source Telephony Project GIT-master-a358458
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
 

Enumerations

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

Functions

struct ast_cc_config_params__ast_cc_config_params_init (const char *file, int line, const char *function)
 Allocate and initialize an ast_cc_config_params structure. More...
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static void agent_destroy (void *data)
 
static const char * agent_policy_to_str (enum ast_cc_agent_policies policy)
 
int ast_cc_agent_accept_request (int core_id, const char *const debug,...)
 Accept inbound CC request. More...
 
struct ast_cc_agentast_cc_agent_callback (int flags, ao2_callback_fn *function, void *args, const char *const type)
 Call a callback on all agents of a specific type. More...
 
int ast_cc_agent_caller_available (int core_id, const char *const debug,...)
 Indicate that a previously unavailable caller has become available. More...
 
int ast_cc_agent_caller_busy (int core_id, const char *debug,...)
 Indicate that the caller is busy. More...
 
int ast_cc_agent_recalling (int core_id, const char *const debug,...)
 Tell the CC core that a caller is currently recalling. More...
 
int ast_cc_agent_register (const struct ast_cc_agent_callbacks *callbacks)
 Register a set of agent callbacks with the core. More...
 
int ast_cc_agent_set_interfaces_chanvar (struct ast_channel *chan)
 Set the first level CC_INTERFACES channel variable for a channel. More...
 
int ast_cc_agent_status_response (int core_id, enum ast_device_state devstate)
 Response with a caller's current status. More...
 
void ast_cc_agent_unregister (const struct ast_cc_agent_callbacks *callbacks)
 Unregister a set of agent callbacks with the core. More...
 
int ast_cc_available_timer_expire (const void *data)
 Scheduler callback for available timer expiration. More...
 
int ast_cc_build_frame (struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, enum ast_cc_service_type service, void *private_data, struct ast_frame *frame)
 Create a CC Control frame. More...
 
void ast_cc_busy_interface (struct ast_channel *inbound, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, void *private_data)
 Callback made from ast_cc_callback for certain channel types. More...
 
void ast_cc_call_failed (struct ast_channel *incoming, struct ast_channel *outgoing, const char *const dialstring)
 Make CCBS available in the case that ast_call fails. More...
 
int ast_cc_call_init (struct ast_channel *chan, int *ignore_cc)
 Start the CC process on a call. More...
 
int ast_cc_callback (struct ast_channel *inbound, const char *const tech, const char *const dest, ast_cc_callback_fn callback)
 Run a callback for potential matching destinations. More...
 
int ast_cc_completed (struct ast_channel *chan, const char *const debug,...)
 Indicate recall has been acknowledged. More...
 
void ast_cc_config_params_destroy (struct ast_cc_config_params *params)
 Free memory from CCSS configuration params. More...
 
void ast_cc_copy_config_params (struct ast_cc_config_params *dest, const struct ast_cc_config_params *src)
 copy CCSS configuration parameters from one structure to another More...
 
void ast_cc_default_config_params (struct ast_cc_config_params *params)
 Set the specified CC config params to default values. More...
 
void ast_cc_extension_monitor_add_dialstring (struct ast_channel *incoming, const char *const dialstring, const char *const device_name)
 Add a child dialstring to an extension monitor. More...
 
int ast_cc_failed (int core_id, const char *const debug,...)
 Indicate failure has occurred. More...
 
int ast_cc_get_current_core_id (struct ast_channel *chan)
 Get the core id for the current call. More...
 
struct ast_cc_monitorast_cc_get_monitor_by_recall_core_id (const int core_id, const char *const device_name)
 Get the associated monitor given the device name and core_id. More...
 
int ast_cc_get_param (struct ast_cc_config_params *params, const char *const name, char *buf, size_t buf_len)
 get a CCSS configuration parameter, given its name More...
 
int ast_cc_is_config_param (const char *const name)
 Is this a CCSS configuration parameter? More...
 
int ast_cc_is_recall (struct ast_channel *chan, int *core_id, const char *const monitor_type)
 Decide if a call to a particular channel is a CC recall. More...
 
int ast_cc_monitor_callee_available (const int core_id, const char *const debug,...)
 Alert the core that a device being monitored has become available. More...
 
int ast_cc_monitor_count (const char *const name, const char *const type)
 Return the number of outstanding CC requests to a specific device. More...
 
int ast_cc_monitor_failed (int core_id, const char *const monitor_name, const char *const debug,...)
 Indicate that a failure has occurred on a specific monitor. More...
 
int ast_cc_monitor_party_b_free (int core_id)
 Alert a caller that though the callee has become free, the caller himself is not and may not call back. More...
 
int ast_cc_monitor_register (const struct ast_cc_monitor_callbacks *callbacks)
 Register a set of monitor callbacks with the core. More...
 
int ast_cc_monitor_request_acked (int core_id, const char *const debug,...)
 Indicate that an outbound entity has accepted our CC request. More...
 
int ast_cc_monitor_status_request (int core_id)
 Request the status of a caller or callers. More...
 
int ast_cc_monitor_stop_ringing (int core_id)
 Alert a caller to stop ringing. More...
 
void ast_cc_monitor_unregister (const struct ast_cc_monitor_callbacks *callbacks)
 Unregister a set of monitor callbacks with the core. More...
 
int ast_cc_offer (struct ast_channel *caller_chan)
 Offer CC to a caller. More...
 
int ast_cc_request_is_within_limits (void)
 Check if the incoming CC request is within the bounds set by the cc_max_requests configuration option. More...
 
int ast_cc_set_param (struct ast_cc_config_params *params, const char *const name, const char *const value)
 set a CCSS configuration parameter, given its name More...
 
const char * ast_get_cc_agent_dialstring (struct ast_cc_config_params *config)
 Get the cc_agent_dialstring. More...
 
enum ast_cc_agent_policies ast_get_cc_agent_policy (struct ast_cc_config_params *config)
 Get the cc_agent_policy. More...
 
const char * ast_get_cc_callback_sub (struct ast_cc_config_params *config)
 Get the name of the callback subroutine. More...
 
unsigned int ast_get_cc_max_agents (struct ast_cc_config_params *config)
 Get the cc_max_agents. More...
 
unsigned int ast_get_cc_max_monitors (struct ast_cc_config_params *config)
 Get the cc_max_monitors. More...
 
enum ast_cc_monitor_policies ast_get_cc_monitor_policy (struct ast_cc_config_params *config)
 Get the cc_monitor_policy. More...
 
unsigned int ast_get_cc_offer_timer (struct ast_cc_config_params *config)
 Get the cc_offer_timer. More...
 
unsigned int ast_get_cc_recall_timer (struct ast_cc_config_params *config)
 Get the cc_recall_timer. More...
 
unsigned int ast_get_ccbs_available_timer (struct ast_cc_config_params *config)
 Get the ccbs_available_timer. More...
 
unsigned int ast_get_ccnr_available_timer (struct ast_cc_config_params *config)
 Get the ccnr_available_timer. More...
 
void ast_handle_cc_control_frame (struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
 Properly react to a CC control frame. More...
 
void ast_ignore_cc (struct ast_channel *chan)
 Mark the channel to ignore further CC activity. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int ast_queue_cc_frame (struct ast_channel *chan, const char *monitor_type, const char *const dialstring, enum ast_cc_service_type service, void *private_data)
 Queue an AST_CONTROL_CC frame. More...
 
void ast_set_cc_agent_dialstring (struct ast_cc_config_params *config, const char *const value)
 Set the cc_agent_dialstring. More...
 
int ast_set_cc_agent_policy (struct ast_cc_config_params *config, enum ast_cc_agent_policies value)
 Set the cc_agent_policy. More...
 
void ast_set_cc_callback_sub (struct ast_cc_config_params *config, const char *const value)
 Set the callback subroutine name. More...
 
int ast_set_cc_interfaces_chanvar (struct ast_channel *chan, const char *const extension)
 Set the CC_INTERFACES channel variable for a channel using an. More...
 
void ast_set_cc_max_agents (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_max_agents. More...
 
void ast_set_cc_max_monitors (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_max_monitors. More...
 
int ast_set_cc_monitor_policy (struct ast_cc_config_params *config, enum ast_cc_monitor_policies value)
 Set the cc_monitor_policy. More...
 
void ast_set_cc_offer_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_offer_timer. More...
 
void ast_set_cc_recall_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the cc_recall_timer. More...
 
void ast_set_ccbs_available_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the ccbs_available_timer. More...
 
void ast_set_ccnr_available_timer (struct ast_cc_config_params *config, unsigned int value)
 Set the ccnr_available_timer. More...
 
int ast_setup_cc_recall_datastore (struct ast_channel *chan, const int core_id)
 Set up a CC recall datastore on a channel. More...
 
static void build_cc_interfaces_chanvar (struct ast_cc_monitor *starting_point, struct ast_str **str)
 
static void call_destructor_with_no_monitor (const char *const monitor_type, void *private_data)
 
static void cancel_available_timer (struct cc_core_instance *core_instance)
 
static int cc_active (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static int cc_agent_callback_helper (void *obj, void *args, int flags)
 
static struct ast_cc_agentcc_agent_init (struct ast_channel *caller_chan, const char *const caller_name, const int core_id, struct cc_monitor_tree *interface_tree)
 
static int cc_available (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static int cc_build_payload (struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *dialstring, enum ast_cc_service_type service, void *private_data, struct cc_control_payload *payload)
 
static int cc_callee_ready (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static int cc_caller_busy (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static int cc_caller_offered (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static int cc_caller_requested (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static int cc_cli_output_status (void *data)
 
static void cc_cli_print_monitor_stats (struct ast_cc_monitor *monitor, int fd, int parent_id)
 
static int cc_complete (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static struct cc_core_instancecc_core_init_instance (struct ast_channel *caller_chan, struct cc_monitor_tree *called_tree, const int core_id, struct cc_control_payload *cc_data)
 
static int cc_core_instance_cmp_fn (void *obj, void *arg, int flags)
 
static void cc_core_instance_destructor (void *data)
 
static int cc_core_instance_hash_fn (const void *obj, const int flags)
 
static struct ast_cc_monitorcc_device_monitor_init (const char *const device_name, const char *const dialstring, const struct cc_control_payload *cc_data, int core_id)
 
static int cc_do_state_change (void *datap)
 
static void cc_extension_monitor_change_is_valid (struct cc_core_instance *core_instance, unsigned int parent_id, const char *const device_name, int is_valid)
 
static void cc_extension_monitor_destructor (void *private_data)
 
static struct ast_cc_monitorcc_extension_monitor_init (const char *const exten, const char *const context, const unsigned int parent_id)
 
static int cc_failed (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static void cc_generic_agent_destructor (struct ast_cc_agent *agent)
 
static int cc_generic_agent_init (struct ast_cc_agent *agent, struct ast_channel *chan)
 
static int cc_generic_agent_recall (struct ast_cc_agent *agent)
 
static void cc_generic_agent_respond (struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
 
static int cc_generic_agent_start_monitoring (struct ast_cc_agent *agent)
 
static int cc_generic_agent_start_offer_timer (struct ast_cc_agent *agent)
 
static int cc_generic_agent_status_request (struct ast_cc_agent *agent)
 
static int cc_generic_agent_stop_offer_timer (struct ast_cc_agent *agent)
 
static int cc_generic_agent_stop_ringing (struct ast_cc_agent *agent)
 
static int cc_generic_is_device_available (enum ast_device_state state)
 
static int cc_generic_monitor_cancel_available_timer (struct ast_cc_monitor *monitor, int *sched_id)
 
static void cc_generic_monitor_destructor (void *private_data)
 
static int cc_generic_monitor_request_cc (struct ast_cc_monitor *monitor, int *available_timer_id)
 
static int cc_generic_monitor_suspend (struct ast_cc_monitor *monitor)
 
static int cc_generic_monitor_unsuspend (struct ast_cc_monitor *monitor)
 
static void cc_interface_destroy (void *data)
 
static void cc_interface_tree_destroy (void *data)
 
static int cc_interfaces_datastore_init (struct ast_channel *chan)
 
static void cc_monitor_destroy (void *data)
 
static int cc_monitor_failed (void *data)
 
static int cc_offer (const int core_id, const char *const debug,...)
 
static int cc_party_b_free (void *data)
 
static int cc_publish (struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
 
static void cc_publish_available (int core_id, const char *callee, const char *service)
 
static void cc_publish_callerrecalling (int core_id, const char *caller)
 
static void cc_publish_callerstartmonitoring (int core_id, const char *caller)
 
static void cc_publish_callerstopmonitoring (int core_id, const char *caller)
 
static void cc_publish_failure (int core_id, const char *caller, const char *reason)
 
static void cc_publish_monitorfailed (int core_id, const char *callee)
 
static void cc_publish_offertimerstart (int core_id, const char *caller, unsigned int expires)
 
static void cc_publish_recallcomplete (int core_id, const char *caller)
 
static void cc_publish_requestacknowledged (int core_id, const char *caller)
 
static void cc_publish_requested (int core_id, const char *caller, const char *callee)
 
static void cc_recall_ds_destroy (void *data)
 
static void * cc_recall_ds_duplicate (void *data)
 
static int cc_recalling (struct cc_core_instance *core_instance, struct cc_state_change_args *args, enum cc_state previous_state)
 
static void * cc_ref (void *obj, const char *debug)
 
static int cc_request_state_change (enum cc_state state, const int core_id, const char *debug, va_list ap)
 
static const char * cc_service_to_string (enum ast_cc_service_type service)
 
static enum ast_device_state cc_state_to_devstate (enum cc_state state)
 
static const char * cc_state_to_string (enum cc_state state)
 
static int cc_status_request (void *data)
 
static int cc_status_response (void *data)
 
static int cc_stop_ringing (void *data)
 
static void cc_unique_append (struct ast_str **str, const char *dialstring)
 
static void * cc_unref (void *obj, const char *debug)
 
static int cccancel_exec (struct ast_channel *chan, const char *data)
 
static int ccreq_exec (struct ast_channel *chan, const char *data)
 
static enum ast_device_state ccss_device_state (const char *device_name)
 
static void ccss_notify_device_state_change (const char *device, enum cc_state state)
 
static void check_callback_sanity (const struct ast_cc_agent_callbacks *callbacks)
 
static char * complete_core_id (const char *word)
 
static long count_agents (const char *const caller, const int core_id_exception)
 
static int count_agents_cb (void *obj, void *arg, void *data, int flags)
 
static int count_monitors_cb (void *obj, void *arg, int flags)
 
static struct generic_monitor_instance_listcreate_new_generic_list (struct ast_cc_monitor *monitor)
 
static void dialed_cc_interfaces_destroy (void *data)
 
static void * dialed_cc_interfaces_duplicate (void *data)
 
static struct extension_monitor_pvtextension_monitor_pvt_init (void)
 
static const struct ast_cc_agent_callbacksfind_agent_callbacks (struct ast_channel *chan)
 
static struct cc_core_instancefind_cc_core_instance (const int core_id)
 
static struct generic_monitor_instance_listfind_generic_monitor_instance_list (const char *const device_name)
 
static const struct ast_cc_monitor_callbacksfind_monitor_callbacks (const char *const type)
 
static void generic_agent_devstate_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static void generic_monitor_devstate_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static int generic_monitor_devstate_tp_cb (void *data)
 
static void generic_monitor_instance_list_destructor (void *obj)
 
static void * generic_recall (void *data)
 
static char * handle_cc_kill (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cc_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int has_device_monitors (struct cc_core_instance *core_instance)
 check if the core instance has any device monitors More...
 
static void initialize_cc_devstate_map (void)
 
static void initialize_cc_devstate_map_helper (struct ast_config *cc_config, enum cc_state state, const char *cc_setting)
 
static void initialize_cc_max_requests (void)
 
static int is_state_change_valid (enum cc_state current_state, const enum cc_state new_state, struct ast_cc_agent *agent)
 
static int kill_cores (void *obj, void *arg, int flags)
 
static void kill_duplicate_offers (char *caller)
 
static int load_module (void)
 
static int match_agent (void *obj, void *arg, void *data, int flags)
 
static const char * monitor_policy_to_str (enum ast_cc_monitor_policies policy)
 
static int offer_timer_expire (const void *data)
 
static int print_stats_cb (void *obj, void *arg, int flags)
 
static void request_cc (struct cc_core_instance *core_instance)
 
static enum ast_cc_agent_policies str_to_agent_policy (const char *const value)
 
static enum ast_cc_monitor_policies str_to_monitor_policy (const char *const value)
 
static void suspend (struct cc_core_instance *core_instance)
 
static int unload_module (void)
 
static void unsuspend (struct cc_core_instance *core_instance)
 

Variables

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

Detailed Description

Call Completion Supplementary Services implementation.

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

Definition in file ccss.c.

Macro Definition Documentation

◆ CC_ACTIVE_DEVSTATE_DEFAULT

#define CC_ACTIVE_DEVSTATE_DEFAULT   AST_DEVICE_INUSE

Definition at line 552 of file ccss.c.

◆ CC_AVAILABLE_DEVSTATE_DEFAULT

#define CC_AVAILABLE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 549 of file ccss.c.

◆ CC_CALLEE_READY_DEVSTATE_DEFAULT

#define CC_CALLEE_READY_DEVSTATE_DEFAULT   AST_DEVICE_RINGING

Definition at line 553 of file ccss.c.

◆ CC_CALLER_BUSY_DEVSTATE_DEFAULT

#define CC_CALLER_BUSY_DEVSTATE_DEFAULT   AST_DEVICE_ONHOLD

Definition at line 554 of file ccss.c.

◆ CC_CALLER_OFFERED_DEVSTATE_DEFAULT

#define CC_CALLER_OFFERED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 550 of file ccss.c.

◆ CC_CALLER_REQUESTED_DEVSTATE_DEFAULT

#define CC_CALLER_REQUESTED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 551 of file ccss.c.

◆ CC_COMPLETE_DEVSTATE_DEFAULT

#define CC_COMPLETE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 556 of file ccss.c.

◆ CC_FAILED_DEVSTATE_DEFAULT

#define CC_FAILED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 557 of file ccss.c.

◆ CC_MAX_AGENTS_DEFAULT

#define CC_MAX_AGENTS_DEFAULT   5

Definition at line 658 of file ccss.c.

◆ CC_MAX_MONITORS_DEFAULT

#define CC_MAX_MONITORS_DEFAULT   5

Definition at line 659 of file ccss.c.

◆ CC_OFFER_TIMER_DEFAULT

#define CC_OFFER_TIMER_DEFAULT   20 /* Seconds */

Definition at line 654 of file ccss.c.

◆ CC_RECALL_TIMER_DEFAULT

#define CC_RECALL_TIMER_DEFAULT   20 /* Seconds */

Definition at line 657 of file ccss.c.

◆ CC_RECALLING_DEVSTATE_DEFAULT

#define CC_RECALLING_DEVSTATE_DEFAULT   AST_DEVICE_RINGING

Definition at line 555 of file ccss.c.

◆ CCBS_AVAILABLE_TIMER_DEFAULT

#define CCBS_AVAILABLE_TIMER_DEFAULT   4800 /* Seconds */

Definition at line 656 of file ccss.c.

◆ CCNR_AVAILABLE_TIMER_DEFAULT

#define CCNR_AVAILABLE_TIMER_DEFAULT   7200 /* Seconds */

Definition at line 655 of file ccss.c.

◆ GLOBAL_CC_MAX_REQUESTS_DEFAULT

#define GLOBAL_CC_MAX_REQUESTS_DEFAULT   20

Definition at line 660 of file ccss.c.

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

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

◆ match_flags

Enumerator
MATCH_NO_REQUEST 
MATCH_REQUEST 

Definition at line 469 of file ccss.c.

469 {
470 /* Only match agents that have not yet
471 * made a CC request
472 */
473 MATCH_NO_REQUEST = (1 << 0),
474 /* Only match agents that have made
475 * a CC request
476 */
477 MATCH_REQUEST = (1 << 1),
478};
@ MATCH_REQUEST
Definition: ccss.c:477
@ MATCH_NO_REQUEST
Definition: ccss.c:473

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

681{
682 struct ast_cc_config_params *params = __ast_malloc(sizeof(*params), file, line, function);
683
684 if (!params) {
685 return NULL;
686 }
687
689 return params;
690}
void * __ast_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:675
#define NULL
Definition: resample.c:96

References __ast_malloc(), ast_cc_default_config_params(), make_ari_stubs::file, and NULL.

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4668 of file ccss.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4668 of file ccss.c.

◆ agent_destroy()

static void agent_destroy ( void *  data)
static

Definition at line 2522 of file ccss.c.

2523{
2524 struct ast_cc_agent *agent = data;
2525
2526 if (agent->callbacks) {
2527 agent->callbacks->destructor(agent);
2528 }
2530}
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:692
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 727 of file ccss.c.

728{
729 switch (policy) {
731 return "never";
733 return "native";
735 return "generic";
736 default:
737 /* This should never happen... */
738 return "";
739 }
740}
@ 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 3741 of file ccss.c.

3742{
3743 va_list ap;
3744 int res;
3745
3746 va_start(ap, debug);
3748 va_end(ap);
3749 return res;
3750}
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3295
static int debug
Global debug status.
Definition: res_xmpp.c:441

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

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

457{
458 struct cc_callback_helper helper = {.function = function, .args = args, .type = type};
459 struct cc_core_instance *core_instance;
460 if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper,
461 "Calling provided agent callback function"))) {
462 struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent");
463 cc_unref(core_instance, "agent callback done with the core_instance");
464 return agent;
465 }
466 return NULL;
467}
#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:149
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
static struct ao2_container * cc_core_instances
Definition: ccss.c:326
static int cc_agent_callback_helper(void *obj, void *args, int flags)
Definition: ccss.c:444
static const char type[]
Definition: chan_ooh323.c:109
ao2_callback_fn * function
Definition: ccss.c:439
struct ast_cc_agent * agent
Definition: ccss.c:340
const char * args

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

3786{
3787 va_list ap;
3788 int res;
3789
3790 va_start(ap, debug);
3791 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3792 va_end(ap);
3793 return res;
3794}

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

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

3775{
3776 va_list ap;
3777 int res;
3778
3779 va_start(ap, debug);
3780 res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap);
3781 va_end(ap);
3782 return res;
3783}

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

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

3797{
3798 va_list ap;
3799 int res;
3800
3801 va_start(ap, debug);
3802 res = cc_request_state_change(CC_RECALLING, core_id, debug, ap);
3803 va_end(ap);
3804 return res;
3805}

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

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

1218{
1219 struct cc_agent_backend *backend = ast_calloc(1, sizeof(*backend));
1220
1221 if (!backend) {
1222 return -1;
1223 }
1224
1225 backend->callbacks = callbacks;
1229 return 0;
1230}
#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.
Definition: linkedlists.h:151
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
struct @468 callbacks
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.c:1212
struct cc_agent_backend * next
Definition: ccss.c:1211

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

Referenced by 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 3596 of file ccss.c.

3597{
3598 struct ast_datastore *recall_datastore;
3599 struct cc_monitor_tree *interface_tree;
3600 struct ast_cc_monitor *monitor;
3601 struct cc_recall_ds_data *recall_data;
3602 struct ast_str *str = ast_str_create(64);
3603 int core_id;
3604
3605 if (!str) {
3606 return -1;
3607 }
3608
3609 ast_channel_lock(chan);
3610 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3611 ast_channel_unlock(chan);
3612 ast_free(str);
3613 return -1;
3614 }
3615 recall_data = recall_datastore->data;
3616 interface_tree = recall_data->interface_tree;
3617 core_id = recall_data->core_id;
3618 ast_channel_unlock(chan);
3619
3620 AST_LIST_LOCK(interface_tree);
3621 monitor = AST_LIST_FIRST(interface_tree);
3623 AST_LIST_UNLOCK(interface_tree);
3624
3625 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3626 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3627 core_id, ast_str_buffer(str));
3628
3629 ast_free(str);
3630 return 0;
3631}
const char * str
Definition: app_jack.c:147
#define ast_free(a)
Definition: astmm.h:180
static const struct ast_datastore_info recall_ds_info
Definition: ccss.c:3366
static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str **str)
Definition: ccss.c:3553
static int cc_logger_level
Definition: ccss.c:133
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unlock(chan)
Definition: channel.h:2923
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
#define ast_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.
Definition: linkedlists.h:140
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
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.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
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:323
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3342

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

4059{
4061 struct cc_core_instance *core_instance;
4062 int res;
4063
4064 args = ast_calloc(1, sizeof(*args));
4065 if (!args) {
4066 return -1;
4067 }
4068
4069 core_instance = find_cc_core_instance(core_id);
4070 if (!core_instance) {
4071 ast_free(args);
4072 return -1;
4073 }
4074
4075 args->core_instance = core_instance;
4076 args->devstate = devstate;
4077
4079 if (res) {
4080 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4081 ast_free(args);
4082 }
4083 return res;
4084}
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
static int cc_status_response(void *data)
Definition: ccss.c:4037
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, and find_cc_core_instance().

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

1233{
1234 struct cc_agent_backend *backend;
1237 if (backend->callbacks == callbacks) {
1239 ast_free(backend);
1240 break;
1241 }
1242 }
1245}
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617

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, and cc_agent_backend::next.

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

1488{
1489 struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data;
1490 int res;
1491 monitor->available_timer_id = -1;
1492 res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor");
1493 cc_unref(monitor, "Unref reference from scheduler\n");
1494 return res;
1495}
int ast_cc_monitor_failed(int core_id, const char *const monitor_name, const char *const debug,...)
Indicate that a failure has occurred on a specific monitor.
Definition: ccss.c:3906
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, and ast_cc_monitor::interface.

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

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

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

4199{
4200 struct cc_control_payload payload;
4201 if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) {
4202 /* Something screwed up. Don't try to handle this payload */
4204 return;
4205 }
4206 ast_handle_cc_control_frame(inbound, NULL, &payload);
4207}
void ast_handle_cc_control_frame(struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data)
Properly react to a CC control frame.
Definition: ccss.c:2293
static void call_destructor_with_no_monitor(const char *const monitor_type, void *private_data)
Definition: ccss.c:2192
@ 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, and cc_control_payload::private_data.

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

4165{
4166 char device_name[AST_CHANNEL_NAME];
4167 struct cc_control_payload payload;
4168 struct ast_cc_config_params *cc_params;
4169
4171 /* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call
4172 * failing is something other than busy or congestion
4173 */
4174 return;
4175 }
4176
4178 if (!cc_params) {
4179 return;
4180 }
4182 /* This sort of CCBS only works if using generic CC. For native, we would end up sending
4183 * a CC request for a non-existent call. The far end will reject this every time
4184 */
4185 return;
4186 }
4187
4188 ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
4189 if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
4190 dialstring, AST_CC_CCBS, NULL, &payload)) {
4191 /* Something screwed up, we can't make a frame with this */
4192 return;
4193 }
4194 ast_handle_cc_control_frame(incoming, outgoing, &payload);
4195}
#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:876
#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:10496
int ast_channel_hangupcause(const struct ast_channel *chan)
#define AST_CHANNEL_NAME
Definition: channel.h:171
struct ast_cc_config_params * ast_channel_get_cc_config_params(struct ast_channel *chan)
Get the CCSS parameters from a channel.
Definition: channel.c:10474

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, and NULL.

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

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

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

References ast_get_channel_tech(), and ast_channel_tech::cc_callback.

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

3808{
3809 struct ast_datastore *recall_datastore;
3810 struct cc_recall_ds_data *recall_data;
3811 int core_id;
3812 va_list ap;
3813 int res;
3814
3815 ast_channel_lock(chan);
3816 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3817 /* Silly! Why did you call this function if there's no recall DS? */
3818 ast_channel_unlock(chan);
3819 return -1;
3820 }
3821 recall_data = recall_datastore->data;
3822 if (recall_data->nested || recall_data->ignore) {
3823 /* If this is being called from a nested Dial, it is too
3824 * early to determine if the recall has actually completed.
3825 * The outermost dial is the only one with the authority to
3826 * declare the recall to be complete.
3827 *
3828 * Similarly, if this function has been called when the
3829 * recall has progressed beyond the first dial, this is not
3830 * a legitimate time to declare the recall to be done. In fact,
3831 * that should have been done already.
3832 */
3833 ast_channel_unlock(chan);
3834 return -1;
3835 }
3836 core_id = recall_data->core_id;
3837 ast_channel_unlock(chan);
3838 va_start(ap, debug);
3840 va_end(ap);
3841 return res;
3842}

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, and recall_ds_info.

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

693{
694 ast_free(params);
695}

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

855{
856 *dest = *src;
857}

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

676{
677 *params = cc_default_params;
678}
static const struct ast_cc_config_params cc_default_params
Definition: ccss.c:662

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

1984{
1985 struct ast_datastore *cc_datastore;
1986 struct dialed_cc_interfaces *cc_interfaces;
1987 struct ast_cc_monitor *monitor;
1988 struct extension_monitor_pvt *extension_pvt;
1989 struct extension_child_dialstring *child_dialstring;
1990 struct cc_monitor_tree *interface_tree;
1991 int id;
1992
1993 ast_channel_lock(incoming);
1994 if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) {
1995 ast_channel_unlock(incoming);
1996 return;
1997 }
1998
1999 cc_interfaces = cc_datastore->data;
2000 interface_tree = cc_interfaces->interface_tree;
2001 id = cc_interfaces->dial_parent_id;
2002 ast_channel_unlock(incoming);
2003
2004 AST_LIST_LOCK(interface_tree);
2005 AST_LIST_TRAVERSE(interface_tree, monitor, next) {
2006 if (monitor->id == id) {
2007 break;
2008 }
2009 }
2010
2011 if (!monitor) {
2012 AST_LIST_UNLOCK(interface_tree);
2013 return;
2014 }
2015
2016 extension_pvt = monitor->private_data;
2017 if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) {
2018 AST_LIST_UNLOCK(interface_tree);
2019 return;
2020 }
2021 ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring));
2022 ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name));
2023 child_dialstring->is_valid = 1;
2024 AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next);
2025 AST_LIST_UNLOCK(interface_tree);
2026}
enum queue_result id
Definition: app_queue.c:1638
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
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:1907
unsigned int dial_parent_id
Definition: ccss.c:1880
Data regarding an extension monitor's child's dialstrings.
Definition: ccss.c:1738
char device_name[AST_CHANNEL_NAME]
The name of the device being dialed.
Definition: ccss.c:1773
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition: ccss.c:1788
char original_dialstring[AST_CHANNEL_NAME]
the original dialstring used to call a particular device
Definition: ccss.c:1754
Private data for an extension monitor.
Definition: ccss.c:1795
struct extension_monitor_pvt::@326 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, and ast_cc_monitor::private_data.

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

3845{
3846 va_list ap;
3847 int res;
3848
3849 va_start(ap, debug);
3850 res = cc_request_state_change(CC_FAILED, core_id, debug, ap);
3851 va_end(ap);
3852 return res;
3853}

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

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

2466{
2467 struct ast_datastore *datastore;
2468 struct dialed_cc_interfaces *cc_interfaces;
2469 int core_id_return;
2470
2471 ast_channel_lock(chan);
2472 if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2473 ast_channel_unlock(chan);
2474 return -1;
2475 }
2476
2477 cc_interfaces = datastore->data;
2478 core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id;
2479 ast_channel_unlock(chan);
2480 return core_id_return;
2481
2482}

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, and NULL.

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

3487{
3488 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3489 struct ast_cc_monitor *monitor_iter;
3490
3491 if (!core_instance) {
3492 return NULL;
3493 }
3494
3495 AST_LIST_LOCK(core_instance->monitors);
3496 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
3497 if (!strcmp(monitor_iter->interface->device_name, device_name)) {
3498 /* Found a monitor. */
3499 cc_ref(monitor_iter, "Hand the requester of the monitor a reference");
3500 break;
3501 }
3502 }
3503 AST_LIST_UNLOCK(core_instance->monitors);
3504 cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id");
3505 return monitor_iter;
3506}
struct ast_cc_monitor * next
Definition: ccss.h:528
struct cc_monitor_tree * monitors
Definition: ccss.c:344

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, and NULL.

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

760{
761 const char *value = NULL;
762
763 if (!strcasecmp(name, "cc_callback_sub")) {
765 } else if (!strcasecmp(name, "cc_agent_policy")) {
767 } else if (!strcasecmp(name, "cc_monitor_policy")) {
769 } else if (!strcasecmp(name, "cc_agent_dialstring")) {
771 }
772 if (value) {
773 ast_copy_string(buf, value, buf_len);
774 return 0;
775 }
776
777 /* The rest of these are all ints of some sort and require some
778 * snprintf-itude
779 */
780
781 if (!strcasecmp(name, "cc_offer_timer")) {
782 snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params));
783 } else if (!strcasecmp(name, "ccnr_available_timer")) {
784 snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params));
785 } else if (!strcasecmp(name, "ccbs_available_timer")) {
786 snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params));
787 } else if (!strcasecmp(name, "cc_max_agents")) {
788 snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params));
789 } else if (!strcasecmp(name, "cc_max_monitors")) {
790 snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params));
791 } else if (!strcasecmp(name, "cc_recall_timer")) {
792 snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params));
793 } else {
794 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
795 return -1;
796 }
797
798 return 0;
799}
#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:923
static const char * agent_policy_to_str(enum ast_cc_agent_policies policy)
Definition: ccss.c:727
unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
Get the cc_offer_timer.
Definition: ccss.c:893
unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
Get the ccbs_available_timer.
Definition: ccss.c:938
unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
Get the ccnr_available_timer.
Definition: ccss.c:908
unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
Get the cc_max_agents.
Definition: ccss.c:967
const char * ast_get_cc_callback_sub(struct ast_cc_config_params *config)
Get the name of the callback subroutine.
Definition: ccss.c:987
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition: ccss.c:977
static const char * monitor_policy_to_str(enum ast_cc_monitor_policies policy)
Definition: ccss.c:742
const char * ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
Get the cc_agent_dialstring.
Definition: ccss.c:953
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 840 of file ccss.c.

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

References name.

Referenced by process_dahdi().

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

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

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, and recall_ds_info.

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

3764{
3765 va_list ap;
3766 int res;
3767
3768 va_start(ap, debug);
3769 res = cc_request_state_change(CC_CALLEE_READY, core_id, debug, ap);
3770 va_end(ap);
3771 return res;
3772}

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

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

4334{
4335 struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,};
4336
4337 ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents");
4338 ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count);
4339 return data.count;
4340}
@ OBJ_NODATA
Definition: astobj2.h:1044
static int count_monitors_cb(void *obj, void *arg, int flags)
Definition: ccss.c:4313
const char * device_name
Definition: ccss.c:4308

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

3907{
3908 struct ast_cc_monitor_failure_data *failure_data;
3909 int res;
3910 va_list ap;
3911
3912 if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) {
3913 return -1;
3914 }
3915
3916 if (!(failure_data->device_name = ast_strdup(monitor_name))) {
3917 ast_free(failure_data);
3918 return -1;
3919 }
3920
3921 va_start(ap, debug);
3922 if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) {
3923 va_end(ap);
3924 ast_free((char *)failure_data->device_name);
3925 ast_free(failure_data);
3926 return -1;
3927 }
3928 va_end(ap);
3929
3930 failure_data->core_id = core_id;
3931
3933 if (res) {
3934 ast_free((char *)failure_data->device_name);
3935 ast_free((char *)failure_data->debug);
3936 ast_free(failure_data);
3937 }
3938 return res;
3939}
#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:3861
const char * device_name
Definition: ccss.c:3856

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, and ast_cc_monitor_failure_data::device_name.

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

4017{
4018 int res;
4019 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4020
4021 if (!core_instance) {
4022 return -1;
4023 }
4024
4026 if (res) {
4027 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4028 }
4029 return res;
4030}
static int cc_party_b_free(void *data)
Definition: ccss.c:4004

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

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

1163{
1164 struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend));
1165
1166 if (!backend) {
1167 return -1;
1168 }
1169
1170 backend->callbacks = callbacks;
1171
1175 return 0;
1176}
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.c:1157
struct cc_monitor_backend * next
Definition: ccss.c:1156

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

Referenced by 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 3752 of file ccss.c.

3753{
3754 va_list ap;
3755 int res;
3756
3757 va_start(ap, debug);
3758 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3759 va_end(ap);
3760 return res;
3761}

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

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

3952{
3953 int res;
3954 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3955
3956 if (!core_instance) {
3957 return -1;
3958 }
3959
3961 if (res) {
3962 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3963 }
3964 return res;
3965}
static int cc_status_request(void *data)
Definition: ccss.c:3941

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

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

3989{
3990 int res;
3991 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3992
3993 if (!core_instance) {
3994 return -1;
3995 }
3996
3998 if (res) {
3999 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4000 }
4001 return res;
4002}
static int cc_stop_ringing(void *data)
Definition: ccss.c:3967

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

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

1196{
1197 struct cc_monitor_backend *backend;
1200 if (backend->callbacks == callbacks) {
1202 ast_free(backend);
1203 break;
1204 }
1205 }
1208}

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, and cc_monitor_backend::next.

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

3717{
3718 int core_id;
3719 int res = -1;
3720 struct ast_datastore *datastore;
3721 struct dialed_cc_interfaces *cc_interfaces;
3722 char cc_is_offerable;
3723
3724 ast_channel_lock(caller_chan);
3725 if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) {
3726 ast_channel_unlock(caller_chan);
3727 return res;
3728 }
3729
3730 cc_interfaces = datastore->data;
3731 cc_is_offerable = cc_interfaces->is_original_caller;
3732 core_id = cc_interfaces->core_id;
3733 ast_channel_unlock(caller_chan);
3734
3735 if (cc_is_offerable) {
3736 res = cc_offer(core_id, "CC offered to caller %s", ast_channel_name(caller_chan));
3737 }
3738 return res;
3739}
static int cc_offer(const int core_id, const char *const debug,...)
Definition: ccss.c:3705
char is_original_caller
Definition: ccss.c:1903

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, and NULL.

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

2461{
2463}
static unsigned int global_cc_max_requests
Definition: ccss.c:137
static int cc_request_count
Definition: ccss.c:141

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

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

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

954{
955 return config->cc_agent_dialstring;
956}
static const char config[]
Definition: chan_ooh323.c:111

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

860{
861 return config->cc_agent_policy;
862}

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

988{
989 return config->cc_callback_sub;
990}

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

968{
969 return config->cc_max_agents;
970}

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

978{
979 return config->cc_max_monitors;
980}

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

877{
878 return config->cc_monitor_policy;
879}

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

894{
895 return config->cc_offer_timer;
896}

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

924{
925 return config->cc_recall_timer;
926}

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

939{
940 return config->ccbs_available_timer;
941}

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

909{
910 return config->ccnr_available_timer;
911}

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

2294{
2295 char *device_name;
2296 char *dialstring;
2297 struct ast_cc_monitor *monitor;
2298 struct ast_datastore *cc_datastore;
2299 struct dialed_cc_interfaces *cc_interfaces;
2300 struct cc_control_payload *cc_data = frame_data;
2301 struct cc_core_instance *core_instance;
2302
2303 device_name = cc_data->device_name;
2304 dialstring = cc_data->dialstring;
2305
2306 ast_channel_lock(inbound);
2307 if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
2308 ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name);
2309 ast_channel_unlock(inbound);
2311 return;
2312 }
2313
2314 cc_interfaces = cc_datastore->data;
2315
2316 if (cc_interfaces->ignore) {
2317 ast_channel_unlock(inbound);
2319 return;
2320 }
2321
2322 if (!cc_interfaces->is_original_caller) {
2323 /* If the is_original_caller is not set on the *inbound* channel, then
2324 * it must be a local channel. As such, we do not want to create a core instance
2325 * or an agent for the local channel. Instead, we want to pass this along to the
2326 * other side of the local channel so that the original caller can benefit.
2327 */
2328 ast_channel_unlock(inbound);
2329 ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data));
2330 return;
2331 }
2332
2333 core_instance = find_cc_core_instance(cc_interfaces->core_id);
2334 if (!core_instance) {
2335 core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree,
2336 cc_interfaces->core_id, cc_data);
2337 if (!core_instance) {
2338 cc_interfaces->ignore = 1;
2339 ast_channel_unlock(inbound);
2341 return;
2342 }
2343 }
2344
2345 ast_channel_unlock(inbound);
2346
2347 /* Yeah this kind of sucks, but luckily most people
2348 * aren't dialing thousands of interfaces on every call
2349 *
2350 * This traversal helps us to not create duplicate monitors in
2351 * case a device queues multiple CC control frames.
2352 */
2353 AST_LIST_LOCK(cc_interfaces->interface_tree);
2354 AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) {
2355 if (!strcmp(monitor->interface->device_name, device_name)) {
2356 ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n",
2357 core_instance->core_id, device_name);
2358 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2359 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2361 return;
2362 }
2363 }
2364 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2365
2366 if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) {
2367 ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name);
2368 cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2370 return;
2371 }
2372
2373 AST_LIST_LOCK(cc_interfaces->interface_tree);
2374 cc_ref(monitor, "monitor tree's reference to the monitor");
2375 AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next);
2376 AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2377
2378 cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0);
2379
2380 cc_publish_available(cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service));
2381
2382 cc_unref(core_instance, "Done with core_instance after handling CC control frame");
2383 cc_unref(monitor, "Unref reference from allocating monitor");
2384}
static void cc_publish_available(int core_id, const char *callee, const char *service)
Definition: ccss.c:1041
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:2907
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:2227
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:2028
static const char * cc_service_to_string(enum ast_cc_service_type service)
Definition: ccss.c:412
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4653
unsigned int parent_id
Definition: ccss.h:490
enum ast_cc_service_type service
Service offered by the endpoint.
Definition: ccss.c:265

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

3686{
3687 struct ast_datastore *cc_datastore;
3688 struct ast_datastore *cc_recall_datastore;
3689 struct dialed_cc_interfaces *cc_interfaces;
3690 struct cc_recall_ds_data *recall_cc_data;
3691
3692 ast_channel_lock(chan);
3693 if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
3694 cc_interfaces = cc_datastore->data;
3695 cc_interfaces->ignore = 1;
3696 }
3697
3698 if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3699 recall_cc_data = cc_recall_datastore->data;
3700 recall_cc_data->ignore = 1;
3701 }
3702 ast_channel_unlock(chan);
3703}

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, and recall_ds_info.

Referenced by dial_exec_full(), and do_forward().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 4668 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 4114 of file ccss.c.

4116{
4117 struct ast_frame frame = {0,};
4118 char device_name[AST_CHANNEL_NAME];
4119 int retval;
4120 struct ast_cc_config_params *cc_params;
4121
4122 cc_params = ast_channel_get_cc_config_params(chan);
4123 if (!cc_params) {
4124 return -1;
4125 }
4126 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4127 if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
4128 ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
4129 return -1;
4130 }
4131
4132 if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) {
4133 /* Frame building failed. We can't use this. */
4134 return -1;
4135 }
4136 retval = ast_queue_frame(chan, &frame);
4137 ast_frfree(&frame);
4138 return retval;
4139}
int ast_cc_monitor_count(const char *const name, const char *const type)
Return the number of outstanding CC requests to a specific device.
Definition: ccss.c:4333
int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, enum ast_cc_service_type service, void *private_data, struct ast_frame *frame)
Create a CC Control frame.
Definition: ccss.c:4141
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139
static ENTRY retval
Definition: hsearch.c:50
#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, retval, 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 958 of file ccss.c.

959{
960 if (ast_strlen_zero(value)) {
961 config->cc_agent_dialstring[0] = '\0';
962 } else {
963 ast_copy_string(config->cc_agent_dialstring, value, sizeof(config->cc_agent_dialstring));
964 }
965}

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

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

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

993{
994 if (ast_strlen_zero(value)) {
995 config->cc_callback_sub[0] = '\0';
996 } else {
997 ast_copy_string(config->cc_callback_sub, value, sizeof(config->cc_callback_sub));
998 }
999}

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

3634{
3635 struct ast_datastore *recall_datastore;
3636 struct cc_monitor_tree *interface_tree;
3637 struct ast_cc_monitor *monitor_iter;
3638 struct cc_recall_ds_data *recall_data;
3639 struct ast_str *str = ast_str_create(64);
3640 int core_id;
3641
3642 if (!str) {
3643 return -1;
3644 }
3645
3646 ast_channel_lock(chan);
3647 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3648 ast_channel_unlock(chan);
3649 ast_free(str);
3650 return -1;
3651 }
3652 recall_data = recall_datastore->data;
3653 interface_tree = recall_data->interface_tree;
3654 core_id = recall_data->core_id;
3655 ast_channel_unlock(chan);
3656
3657 AST_LIST_LOCK(interface_tree);
3658 AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) {
3659 if (!strcmp(monitor_iter->interface->device_name, extension)) {
3660 break;
3661 }
3662 }
3663
3664 if (!monitor_iter) {
3665 /* We couldn't find this extension. This may be because
3666 * we have been directed into an unexpected extension because
3667 * the admin has changed a CC_INTERFACES variable at some point.
3668 */
3669 AST_LIST_UNLOCK(interface_tree);
3670 ast_free(str);
3671 return -1;
3672 }
3673
3674 build_cc_interfaces_chanvar(monitor_iter, &str);
3675 AST_LIST_UNLOCK(interface_tree);
3676
3677 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3678 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3679 core_id, ast_str_buffer(str));
3680
3681 ast_free(str);
3682 return 0;
3683}
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, 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 972 of file ccss.c.

973{
974 config->cc_max_agents = value;
975}

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

983{
984 config->cc_max_monitors = value;
985}

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

882{
883 /* Screw C and its weak type checking for making me have to do this
884 * validation at runtime.
885 */
886 if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) {
887 return -1;
888 }
889 config->cc_monitor_policy = value;
890 return 0;
891}
@ 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 898 of file ccss.c.

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

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

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

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

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

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

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

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

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

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

3554{
3555 struct extension_monitor_pvt *extension_pvt;
3556 struct extension_child_dialstring *child_dialstring;
3557 struct ast_cc_monitor *monitor_iter = starting_point;
3558 int top_level_id = starting_point->id;
3559 size_t length;
3560
3561 /* Init to an empty string. */
3562 ast_str_truncate(*str, 0);
3563
3564 /* First we need to take all of the is_valid child_dialstrings from
3565 * the extension monitor we found and add them to the CC_INTERFACES
3566 * chanvar
3567 */
3568 extension_pvt = starting_point->private_data;
3569 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
3570 if (child_dialstring->is_valid) {
3571 cc_unique_append(str, child_dialstring->original_dialstring);
3572 }
3573 }
3574
3575 /* And now we get the dialstrings from each of the device monitors */
3576 while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) {
3577 if (monitor_iter->parent_id == top_level_id) {
3578 cc_unique_append(str, monitor_iter->dialstring);
3579 }
3580 }
3581
3582 /* str will have an extra '&' tacked onto the end of it, so we need
3583 * to get rid of that.
3584 */
3585 length = ast_str_strlen(*str);
3586 if (length) {
3587 ast_str_truncate(*str, length - 1);
3588 }
3589 if (length <= 1) {
3590 /* Nothing to recall? This should not happen. */
3591 ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n",
3592 starting_point->interface->device_name);
3593 }
3594}
static void cc_unique_append(struct ast_str **str, const char *dialstring)
Definition: ccss.c:3524
#define LOG_ERROR
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
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 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 2192 of file ccss.c.

2193{
2194 const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type);
2195
2196 if (!monitor_callbacks) {
2197 return;
2198 }
2199
2200 monitor_callbacks->destructor(private_data);
2201}
static const struct ast_cc_monitor_callbacks * find_monitor_callbacks(const char *const type)
Definition: ccss.c:1178
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 3193 of file ccss.c.

3194{
3195 struct ast_cc_monitor *monitor_iter;
3196 AST_LIST_LOCK(core_instance->monitors);
3197 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3198 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3199 if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) {
3201 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3202 monitor_iter->interface->device_name, 1);
3203 cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor");
3204 }
3205 }
3206 }
3208
3209 if (!has_device_monitors(core_instance)) {
3210 ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers");
3211 }
3212 AST_LIST_UNLOCK(core_instance->monitors);
3213}
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:3060
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3844
@ AST_CC_DEVICE_MONITOR
Definition: ccss.h:463
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
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 3135 of file ccss.c.

3136{
3137 /* Either
3138 * 1. Callee accepted CC request, call agent's ack callback.
3139 * 2. Caller became available, call agent's stop_monitoring callback and
3140 * call monitor's unsuspend callback.
3141 */
3142 if (previous_state == CC_CALLER_REQUESTED) {
3143 core_instance->agent->callbacks->respond(core_instance->agent,
3145 cc_publish_requestacknowledged(core_instance->core_id, core_instance->agent->device_name);
3146 } else if (previous_state == CC_CALLER_BUSY) {
3147 cc_publish_callerstopmonitoring(core_instance->core_id, core_instance->agent->device_name);
3148 unsuspend(core_instance);
3149 }
3150 /* Not possible for previous_state to be anything else due to the is_state_change_valid check at the beginning */
3151 return 0;
3152}
static void cc_publish_requestacknowledged(int core_id, const char *caller)
Definition: ccss.c:1077
static void unsuspend(struct cc_core_instance *core_instance)
Definition: ccss.c:3113
static void cc_publish_callerstopmonitoring(int core_id, const char *caller)
Definition: ccss.c:1088
@ 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 444 of file ccss.c.

445{
446 struct cc_core_instance *core_instance = obj;
447 struct cc_callback_helper *helper = args;
448
449 if (strcmp(core_instance->agent->callbacks->type, helper->type)) {
450 return 0;
451 }
452
453 return helper->function(core_instance->agent, helper->args, flags);
454}
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:857
const char * type
Definition: ccss.c:441
void * args
Definition: ccss.c:440

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

2535{
2536 struct ast_cc_agent *agent;
2537 struct ast_cc_config_params *cc_params;
2538
2539 if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy,
2540 "Allocating new ast_cc_agent"))) {
2541 return NULL;
2542 }
2543
2544 agent->core_id = core_id;
2545 strcpy(agent->device_name, caller_name);
2546
2547 cc_params = ast_channel_get_cc_config_params(caller_chan);
2548 if (!cc_params) {
2549 cc_unref(agent, "Could not get channel config params.");
2550 return NULL;
2551 }
2552 if (!(agent->cc_params = ast_cc_config_params_init())) {
2553 cc_unref(agent, "Could not init agent config params.");
2554 return NULL;
2555 }
2556 ast_cc_copy_config_params(agent->cc_params, cc_params);
2557
2558 if (!(agent->callbacks = find_agent_callbacks(caller_chan))) {
2559 cc_unref(agent, "Could not find agent callbacks.");
2560 return NULL;
2561 }
2563
2564 if (agent->callbacks->init(agent, caller_chan)) {
2565 cc_unref(agent, "Agent init callback failed.");
2566 return NULL;
2567 }
2568 ast_log_dynamic_level(cc_logger_level, "Core %u: Created an agent for caller %s\n",
2569 agent->core_id, agent->device_name);
2570 return agent;
2571}
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:407
static void agent_destroy(void *data)
Definition: ccss.c:2522
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:854
static void check_callback_sanity(const struct ast_cc_agent_callbacks *callbacks)
Definition: ccss.c:2510
static const struct ast_cc_agent_callbacks * find_agent_callbacks(struct ast_channel *chan)
Definition: ccss.c:1247
#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 3024 of file ccss.c.

3025{
3026 /* This should never happen... */
3027 ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n");
3028 return -1;
3029}

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

4089{
4090 struct ast_datastore *datastore;
4091 struct dialed_cc_interfaces *cc_interfaces;
4092 int dial_parent_id;
4093
4094 ast_channel_lock(chan);
4096 if (!datastore) {
4097 ast_channel_unlock(chan);
4098 return -1;
4099 }
4100 cc_interfaces = datastore->data;
4101 dial_parent_id = cc_interfaces->dial_parent_id;
4102 ast_channel_unlock(chan);
4103
4104 payload->monitor_type = monitor_type;
4105 payload->private_data = private_data;
4106 payload->service = service;
4107 ast_cc_copy_config_params(&payload->config_params, cc_params);
4109 ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
4110 ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring));
4111 return 0;
4112}
int parent_interface_id
ID of parent extension.
Definition: ccss.c:283
struct ast_cc_config_params config_params
Configuration parameters used by this endpoint.
Definition: ccss.c:274

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

3155{
3156 core_instance->agent->callbacks->callee_available(core_instance->agent);
3157 return 0;
3158}
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 3182 of file ccss.c.

3183{
3184 /* Callee was available, but caller was busy, call agent's begin_monitoring callback
3185 * and call monitor's suspend callback.
3186 */
3187 suspend(core_instance);
3188 core_instance->agent->callbacks->start_monitoring(core_instance->agent);
3189 cc_publish_callerstartmonitoring(core_instance->core_id, core_instance->agent->device_name);
3190 return 0;
3191}
static void cc_publish_callerstartmonitoring(int core_id, const char *caller)
Definition: ccss.c:1099
static void suspend(struct cc_core_instance *core_instance)
Definition: ccss.c:3160
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 3031 of file ccss.c.

3032{
3033 if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) {
3034 ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n",
3035 core_instance->agent->device_name);
3036 return -1;
3037 }
3038 cc_publish_offertimerstart(core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer);
3039 ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n",
3040 core_instance->core_id, core_instance->agent->device_name);
3041 return 0;
3042}
static void cc_publish_offertimerstart(int core_id, const char *caller, unsigned int expires)
Definition: ccss.c:1053
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:164

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

3100{
3102 ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n");
3103 core_instance->agent->callbacks->respond(core_instance->agent,
3105 ast_cc_failed(core_instance->core_id, "Too many requests in the system");
3106 return -1;
3107 }
3108 core_instance->agent->callbacks->stop_offer_timer(core_instance->agent);
3109 request_cc(core_instance);
3110 return 0;
3111}
static void request_cc(struct cc_core_instance *core_instance)
Definition: ccss.c:3075
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:2460
@ 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 4459 of file ccss.c.

4460{
4461 int *cli_fd = data;
4463
4464 if (!count) {
4465 ast_cli(*cli_fd, "There are currently no active call completion transactions\n");
4466 } else {
4467 ast_cli(*cli_fd, "%d Call completion transactions\n", count);
4468 ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n");
4469 ast_cli(*cli_fd, "----------------------------------------------------------------------------\n");
4470 ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI");
4471 }
4472 ast_free(cli_fd);
4473 return 0;
4474}
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:4446
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 4426 of file ccss.c.

4427{
4428 struct ast_cc_monitor *child_monitor_iter = monitor;
4429 if (!monitor) {
4430 return;
4431 }
4432
4433 ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name);
4435 ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered));
4436 }
4437 ast_cli(fd, "\n");
4438
4439 while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) {
4440 if (child_monitor_iter->parent_id == monitor->id) {
4441 cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id);
4442 }
4443 }
4444}
static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
Definition: ccss.c:4426
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 3224 of file ccss.c.

3225{
3226 /* Recall has made progress, call agent and monitor destructor functions
3227 */
3228 cc_publish_recallcomplete(core_instance->core_id, core_instance->agent->device_name);
3229 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed");
3230 return 0;
3231}
#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:1121

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

2909{
2910 char caller[AST_CHANNEL_NAME];
2911 struct cc_core_instance *core_instance;
2912 struct ast_cc_config_params *cc_params;
2913 long agent_count;
2914 int recall_core_id;
2915
2916 ast_channel_get_device_name(caller_chan, caller, sizeof(caller));
2917 cc_params = ast_channel_get_cc_config_params(caller_chan);
2918 if (!cc_params) {
2919 ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n",
2920 caller);
2921 return NULL;
2922 }
2923 /* First, we need to kill off other pending CC offers from caller. If the caller is going
2924 * to request a CC service, it may only be for the latest call he made.
2925 */
2927 kill_duplicate_offers(caller);
2928 }
2929
2930 ast_cc_is_recall(caller_chan, &recall_core_id, NULL);
2931 agent_count = count_agents(caller, recall_core_id);
2932 if (agent_count >= ast_get_cc_max_agents(cc_params)) {
2933 ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller);
2934 return NULL;
2935 }
2936
2937 /* Generic agents can only have a single outstanding CC request per caller. */
2938 if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
2939 ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n");
2940 return NULL;
2941 }
2942
2943 /* Next, we need to create the core instance for this call */
2944 if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) {
2945 return NULL;
2946 }
2947
2948 core_instance->core_id = core_id;
2949 if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) {
2950 cc_unref(core_instance, "Couldn't allocate agent, unref core_instance");
2951 return NULL;
2952 }
2953
2954 core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree");
2955
2956 ao2_t_link(cc_core_instances, core_instance, "Link core instance into container");
2957
2958 return core_instance;
2959}
#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:3405
static void kill_duplicate_offers(char *caller)
Definition: ccss.c:2493
static void cc_core_instance_destructor(void *data)
Definition: ccss.c:2895
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:2532
static long count_agents(const char *const caller, const int core_id_exception)
Definition: ccss.c:2484

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

424{
425 struct cc_core_instance *core_instance1 = obj;
426 struct cc_core_instance *core_instance2 = arg;
427
428 return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0;
429}
@ 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 2895 of file ccss.c.

2896{
2897 struct cc_core_instance *core_instance = data;
2898 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id);
2899 if (core_instance->agent) {
2900 cc_unref(core_instance->agent, "Core instance is done with the agent now");
2901 }
2902 if (core_instance->monitors) {
2903 core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list");
2904 }
2905}

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

418{
419 const struct cc_core_instance *core_instance = obj;
420 return core_instance->core_id;
421}

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

2228{
2229 struct ast_cc_interface *cc_interface;
2230 struct ast_cc_monitor *monitor;
2231 size_t device_name_len = strlen(device_name);
2232 int parent_id = cc_data->parent_interface_id;
2233
2234 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy,
2235 "Allocating new ast_cc_interface"))) {
2236 return NULL;
2237 }
2238
2239 if (!(cc_interface->config_params = ast_cc_config_params_init())) {
2240 cc_unref(cc_interface, "Failed to allocate config params, unref interface");
2241 return NULL;
2242 }
2243
2244 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
2245 cc_unref(cc_interface, "Failed to allocate monitor, unref interface");
2246 return NULL;
2247 }
2248
2249 if (!(monitor->dialstring = ast_strdup(dialstring))) {
2250 cc_unref(monitor, "Failed to copy dialable name. Unref monitor");
2251 cc_unref(cc_interface, "Failed to copy dialable name");
2252 return NULL;
2253 }
2254
2255 if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) {
2256 cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor");
2257 cc_unref(cc_interface, "Failed to find monitor callbacks");
2258 return NULL;
2259 }
2260
2261 strcpy(cc_interface->device_name, device_name);
2263 monitor->parent_id = parent_id;
2264 monitor->core_id = core_id;
2265 monitor->service_offered = cc_data->service;
2266 monitor->private_data = cc_data->private_data;
2267 cc_interface->monitor_type = cc_data->monitor_type;
2268 cc_interface->monitor_class = AST_CC_DEVICE_MONITOR;
2269 monitor->interface = cc_interface;
2270 monitor->available_timer_id = -1;
2271 ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params);
2272 ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %u and parent %u\n",
2273 monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id);
2274 return monitor;
2275}
static int dialed_cc_interface_counter
Definition: ccss.c:1853
static void cc_interface_destroy(void *data)
Definition: ccss.c:1715
static void cc_monitor_destroy(void *data)
Definition: ccss.c:1815
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:757
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 3252 of file ccss.c.

3253{
3254 struct cc_state_change_args *args = datap;
3255 struct cc_core_instance *core_instance;
3256 enum cc_state previous_state;
3257 int res;
3258
3259 ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %u requested. Reason: %s\n",
3260 args->core_id, args->state, args->debug);
3261
3262 core_instance = args->core_instance;
3263
3264 if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) {
3265 ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n",
3266 args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state));
3267 if (args->state == CC_CALLER_REQUESTED) {
3268 /*
3269 * For out-of-order requests, we need to let the requester know that
3270 * we can't handle the request now.
3271 */
3272 core_instance->agent->callbacks->respond(core_instance->agent,
3274 }
3275 ast_free(args);
3276 cc_unref(core_instance, "Unref core instance from when it was found earlier");
3277 return -1;
3278 }
3279
3280 /* We can change to the new state now. */
3281 previous_state = core_instance->current_state;
3282 core_instance->current_state = args->state;
3283 res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state);
3284
3285 /* If state change successful then notify any device state watchers of the change */
3286 if (!res && !strcmp(core_instance->agent->callbacks->type, "generic")) {
3287 ccss_notify_device_state_change(core_instance->agent->device_name, core_instance->current_state);
3288 }
3289
3290 ast_free(args);
3291 cc_unref(core_instance, "Unref since state change has completed"); /* From ao2_find */
3292 return res;
3293}
static int(*const state_change_funcs[])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state)
Definition: ccss.c:3240
static void ccss_notify_device_state_change(const char *device, enum cc_state state)
Definition: ccss.c:641
cc_state
The states used in the CCSS core state machine.
Definition: ccss.c:180
static const char * cc_state_to_string(enum cc_state state)
Definition: ccss.c:407
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:2968
@ AST_CC_AGENT_RESPONSE_FAILURE_INVALID
Definition: ccss.h:845
enum cc_state current_state
Definition: ccss.c:336

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

2029{
2030 struct ast_cc_monitor *monitor_iter;
2031 struct extension_monitor_pvt *extension_pvt;
2032 struct extension_child_dialstring *child_dialstring;
2033
2034 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
2035 if (monitor_iter->id == parent_id) {
2036 break;
2037 }
2038 }
2039
2040 if (!monitor_iter) {
2041 return;
2042 }
2043 extension_pvt = monitor_iter->private_data;
2044
2045 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
2046 if (!strcmp(child_dialstring->device_name, device_name)) {
2047 child_dialstring->is_valid = is_valid;
2048 break;
2049 }
2050 }
2051}
struct extension_child_dialstring * next
Definition: ccss.c:1789

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

1800{
1801 struct extension_monitor_pvt *extension_pvt = private_data;
1802 struct extension_child_dialstring *child_dialstring;
1803
1804 /* This shouldn't be possible, but I'm paranoid */
1805 if (!extension_pvt) {
1806 return;
1807 }
1808
1809 while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) {
1810 ast_free(child_dialstring);
1811 }
1812 ast_free(extension_pvt);
1813}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833

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

2068{
2070 struct ast_cc_interface *cc_interface;
2071 struct ast_cc_monitor *monitor;
2072
2073 ast_str_set(&str, 0, "%s@%s", exten, context);
2074
2075 if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy,
2076 "Allocating new ast_cc_interface"))) {
2077 return NULL;
2078 }
2079
2080 if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
2081 cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface");
2082 return NULL;
2083 }
2084
2085 if (!(monitor->private_data = extension_monitor_pvt_init())) {
2086 cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor");
2087 cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface");
2088 }
2089
2091 monitor->parent_id = parent_id;
2092 cc_interface->monitor_type = "extension";
2094 strcpy(cc_interface->device_name, ast_str_buffer(str));
2095 monitor->interface = cc_interface;
2096 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);
2097 return monitor;
2098}
static struct extension_monitor_pvt * extension_monitor_pvt_init(void)
Definition: ccss.c:1973
@ 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(), voicemailpwcheck::context, 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 3233 of file ccss.c.

3234{
3235 cc_publish_failure(core_instance->core_id, core_instance->agent->device_name, args->debug);
3236 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed");
3237 return 0;
3238}
static void cc_publish_failure(int core_id, const char *caller, const char *reason)
Definition: ccss.c:1132

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

2879{
2881
2882 if (!agent_pvt) {
2883 /* The agent constructor probably failed. */
2884 return;
2885 }
2886
2888 if (agent_pvt->sub) {
2890 }
2891
2893}
static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
Definition: ccss.c:2700
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:971
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 2647 of file ccss.c.

2648{
2649 struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
2650
2651 if (!generic_pvt) {
2652 return -1;
2653 }
2654
2655 generic_pvt->offer_timer_id = -1;
2656 if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
2657 ast_copy_string(generic_pvt->cid_num, ast_channel_caller(chan)->id.number.str, sizeof(generic_pvt->cid_num));
2658 }
2659 if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
2660 ast_copy_string(generic_pvt->cid_name, ast_channel_caller(chan)->id.name.str, sizeof(generic_pvt->cid_name));
2661 }
2662 ast_copy_string(generic_pvt->exten, ast_channel_exten(chan), sizeof(generic_pvt->exten));
2663 ast_copy_string(generic_pvt->context, ast_channel_context(chan), sizeof(generic_pvt->context));
2664 agent->private_data = generic_pvt;
2666 return 0;
2667}
@ 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:2644
char cid_num[AST_CHANNEL_NAME]
Definition: ccss.c:2620
char cid_name[AST_CHANNEL_NAME]
Definition: ccss.c:2628
char exten[AST_CHANNEL_NAME]
Definition: ccss.c:2636
Number structure.
Definition: app_followme.c:154
#define ast_set_flag(p, flag)
Definition: utils.h:70

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

2863{
2864 pthread_t clotho;
2865 enum ast_device_state current_state = ast_device_state(agent->device_name);
2866
2867 if (!cc_generic_is_device_available(current_state)) {
2868 /* We can't try to contact the device right now because he's not available
2869 * Let the core know he's busy.
2870 */
2871 ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name);
2872 return 0;
2873 }
2875 return 0;
2876}
int ast_cc_agent_caller_busy(int core_id, const char *debug,...)
Indicate that the caller is busy.
Definition: ccss.c:3774
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1291
static void * generic_recall(void *data)
Definition: ccss.c:2794
ast_device_state
Device States.
Definition: devicestate.h:52
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:597

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

2714{
2715 /* The generic agent doesn't have to do anything special to
2716 * acknowledge a CC request. Just return.
2717 */
2718 return;
2719}

◆ cc_generic_agent_start_monitoring()

static int cc_generic_agent_start_monitoring ( struct ast_cc_agent agent)
static

Definition at line 2769 of file ccss.c.

2770{
2771 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2772 struct ast_str *str = ast_str_alloca(128);
2773 struct stasis_topic *device_specific_topic;
2774
2775 ast_assert(generic_pvt->sub == NULL);
2776 ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n",
2777 agent->device_name);
2778
2779 device_specific_topic = ast_device_state_topic(agent->device_name);
2780 if (!device_specific_topic) {
2781 return -1;
2782 }
2783
2784 if (!(generic_pvt->sub = stasis_subscribe(device_specific_topic, generic_agent_devstate_cb, agent))) {
2785 return -1;
2786 }
2790 cc_ref(agent, "Ref agent for subscription");
2791 return 0;
2792}
static void generic_agent_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: ccss.c:2739
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.
Definition: devicestate.c:683
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:1023
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:1077
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:649
struct stasis_subscription * sub
Definition: ccss.c:2606

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

2682{
2683 int when;
2684 int sched_id;
2685 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2686
2688 ast_assert(agent->cc_params != NULL);
2689
2690 when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
2691 ast_log_dynamic_level(cc_logger_level, "Core %u: About to schedule offer timer expiration for %d ms\n",
2692 agent->core_id, when);
2693 if ((sched_id = ast_sched_add(cc_sched_context, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) {
2694 return -1;
2695 }
2696 generic_pvt->offer_timer_id = sched_id;
2697 return 0;
2698}
static struct ast_sched_context * cc_sched_context
Definition: ccss.c:115
static int offer_timer_expire(const void *data)
Definition: ccss.c:2669
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 2721 of file ccss.c.

2722{
2724 return 0;
2725}
int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate)
Response with a caller's current status.
Definition: ccss.c:4058

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

2701{
2702 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2703
2704 if (generic_pvt->offer_timer_id != -1) {
2705 if (!ast_sched_del(cc_sched_context, generic_pvt->offer_timer_id)) {
2706 cc_unref(agent, "Remove scheduler's reference to the agent");
2707 }
2708 generic_pvt->offer_timer_id = -1;
2709 }
2710 return 0;
2711}
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 2727 of file ccss.c.

2728{
2729 struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name));
2730
2731 if (!recall_chan) {
2732 return 0;
2733 }
2734
2736 return 0;
2737}
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:1434
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1148
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 1629 of file ccss.c.

1630{
1632
1633 if (*sched_id == -1) {
1634 return 0;
1635 }
1636
1637 ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n",
1638 monitor->core_id, monitor->interface->device_name);
1640 cc_unref(monitor, "Remove scheduler's reference to the monitor");
1641 }
1642 *sched_id = -1;
1643 return 0;
1644}

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

1647{
1648 struct generic_monitor_pvt *gen_mon_pvt = private_data;
1649 struct generic_monitor_instance_list *generic_list;
1650 struct generic_monitor_instance *generic_instance;
1651
1652 if (!private_data) {
1653 /* If the private data is NULL, that means that the monitor hasn't even
1654 * been created yet, but that the destructor was called. While this sort
1655 * of behavior is useful for native monitors, with a generic one, there is
1656 * nothing in particular to do.
1657 */
1658 return;
1659 }
1660
1661 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n",
1662 gen_mon_pvt->core_id, gen_mon_pvt->device_name);
1663
1664 if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) {
1665 /* If there's no generic list, that means that the monitor is being destroyed
1666 * before we actually got to request CC. Not a biggie. Same in the situation
1667 * below if the list traversal should complete without finding an entry.
1668 */
1669 ast_free((char *)gen_mon_pvt->device_name);
1670 ast_free(gen_mon_pvt);
1671 return;
1672 }
1673
1674 AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) {
1675 if (generic_instance->core_id == gen_mon_pvt->core_id) {
1677 ast_free(generic_instance);
1678 break;
1679 }
1680 }
1682
1683 if (AST_LIST_EMPTY(&generic_list->list)) {
1684 /* No more monitors with this device name exist. Time to unlink this
1685 * list from the container
1686 */
1687 ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container");
1688 } else {
1689 /* There are still instances for this particular device. The situation
1690 * may be that we were attempting a CC recall and a failure occurred, perhaps
1691 * on the agent side. If a failure happens here and the device being monitored
1692 * is available, then we need to signal on the first unsuspended instance that
1693 * the device is available for recall.
1694 */
1695
1696 /* First things first. We don't even want to consider this action if
1697 * the device in question isn't available right now.
1698 */
1699 if (generic_list->fit_for_recall
1701 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1702 if (!generic_instance->is_suspended && generic_instance->monitoring) {
1703 ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor "
1704 "availability due to other instance's failure.");
1705 break;
1706 }
1707 }
1708 }
1709 }
1710 cc_unref(generic_list, "Done with generic list in generic monitor destructor");
1711 ast_free((char *)gen_mon_pvt->device_name);
1712 ast_free(gen_mon_pvt);
1713}
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:3763
struct ao2_container * generic_monitors
Definition: ccss.c:1311
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1364
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
enum ast_device_state current_state
Definition: ccss.c:1322
struct generic_monitor_instance_list::@324 list
struct generic_monitor_instance * next
Definition: ccss.c:1317
private data for generic device monitor
Definition: ccss.c:1346
const char * device_name
Definition: ccss.c:1351

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

1498{
1499 struct generic_monitor_instance_list *generic_list;
1500 struct generic_monitor_instance *generic_instance;
1501 struct generic_monitor_pvt *gen_mon_pvt;
1503 int when;
1504
1505 /* First things first. Native channel drivers will have their private data allocated
1506 * at the time that they tell the core that they can offer CC. Generic is quite a bit
1507 * different, and we wait until this point to allocate our private data.
1508 */
1509 if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) {
1510 return -1;
1511 }
1512
1513 if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) {
1514 ast_free(gen_mon_pvt);
1515 return -1;
1516 }
1517
1518 gen_mon_pvt->core_id = monitor->core_id;
1519
1520 monitor->private_data = gen_mon_pvt;
1521
1522 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1523 if (!(generic_list = create_new_generic_list(monitor))) {
1524 return -1;
1525 }
1526 }
1527
1528 if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) {
1529 /* The generic monitor destructor will take care of the appropriate
1530 * deallocations
1531 */
1532 cc_unref(generic_list, "Generic monitor instance failed to allocate");
1533 return -1;
1534 }
1535 generic_instance->core_id = monitor->core_id;
1536 generic_instance->monitoring = 1;
1537 AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next);
1539 ast_get_ccnr_available_timer(monitor->interface->config_params);
1540
1541 *available_timer_id = ast_sched_add(cc_sched_context, when * 1000,
1542 ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference"));
1543 if (*available_timer_id == -1) {
1544 cc_unref(monitor, "Failed to schedule available timer. (monitor)");
1545 cc_unref(generic_list, "Failed to schedule available timer. (generic_list)");
1546 return -1;
1547 }
1548 /* If the new instance was created as CCNR, then that means this device is not currently
1549 * fit for recall even if it previously was.
1550 */
1551 if (service == AST_CC_CCNR || service == AST_CC_CCNL) {
1552 generic_list->fit_for_recall = 0;
1553 }
1554 ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.",
1555 monitor->interface->device_name);
1556 cc_unref(generic_list, "Finished with monitor instance reference in request cc callback");
1557 return 0;
1558}
int ast_cc_available_timer_expire(const void *data)
Scheduler callback for available timer expiration.
Definition: ccss.c:1487
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:3752
static struct generic_monitor_instance_list * create_new_generic_list(struct ast_cc_monitor *monitor)
Definition: ccss.c:1387
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 1560 of file ccss.c.

1561{
1562 struct generic_monitor_instance_list *generic_list;
1563 struct generic_monitor_instance *generic_instance;
1565
1566 if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1567 return -1;
1568 }
1569
1570 /* First we need to mark this particular monitor as being suspended. */
1571 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1572 if (generic_instance->core_id == monitor->core_id) {
1573 generic_instance->is_suspended = 1;
1574 break;
1575 }
1576 }
1577
1578 /* If the device being suspended is currently in use, then we don't need to
1579 * take any further actions
1580 */
1582 cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list.");
1583 return 0;
1584 }
1585
1586 /* If the device is not in use, though, then it may be possible to report the
1587 * device's availability using a different monitor which is monitoring the
1588 * same device
1589 */
1590
1591 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1592 if (!generic_instance->is_suspended) {
1593 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1594 break;
1595 }
1596 }
1597 cc_unref(generic_list, "Done with generic list in suspend callback");
1598 return 0;
1599}

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

1602{
1603 struct generic_monitor_instance *generic_instance;
1606
1607 if (!generic_list) {
1608 return -1;
1609 }
1610 /* If the device is currently available, we can immediately announce
1611 * its availability
1612 */
1614 ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available");
1615 }
1616
1617 /* In addition, we need to mark this generic_monitor_instance as not being suspended anymore */
1618 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1619 if (generic_instance->core_id == monitor->core_id) {
1620 generic_instance->is_suspended = 0;
1621 generic_instance->monitoring = 1;
1622 break;
1623 }
1624 }
1625 cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend");
1626 return 0;
1627}

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

1716{
1717 struct ast_cc_interface *interface = data;
1718 ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name);
1719 ast_cc_config_params_destroy(interface->config_params);
1720}

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

1837{
1838 struct cc_monitor_tree *cc_interface_tree = data;
1839 struct ast_cc_monitor *monitor;
1840 while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
1841 if (monitor->callbacks) {
1842 monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id);
1843 }
1844 cc_unref(monitor, "Destroying all monitors");
1845 }
1846 AST_LIST_HEAD_DESTROY(cc_interface_tree);
1847}
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:653

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

2116 {
2118 struct ast_cc_monitor *monitor;
2119 struct ast_datastore *dial_cc_datastore;
2120
2121 /*XXX This may be a bit controversial. In an attempt to not allocate
2122 * extra resources, I make sure that a future request will be within
2123 * limits. The problem here is that it is reasonable to think that
2124 * even if we're not within the limits at this point, we may be by
2125 * the time the requestor will have made his request. This may be
2126 * deleted at some point.
2127 */
2129 return 0;
2130 }
2131
2132 if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) {
2133 return -1;
2134 }
2135
2136 if (!(monitor = cc_extension_monitor_init(ast_channel_exten(chan), ast_channel_context(chan), 0))) {
2138 return -1;
2139 }
2140
2141 if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) {
2142 cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor");
2144 return -1;
2145 }
2146
2147 if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy,
2148 "Allocate monitor tree"))) {
2149 ast_datastore_free(dial_cc_datastore);
2150 cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor");
2152 return -1;
2153 }
2154
2155 /* Finally, all that allocation is done... */
2156 AST_LIST_HEAD_INIT(interfaces->interface_tree);
2157 AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
2158 cc_ref(monitor, "List's reference to extension monitor");
2159 dial_cc_datastore->data = interfaces;
2160 dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
2161 interfaces->dial_parent_id = monitor->id;
2162 interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1);
2163 interfaces->is_original_caller = 1;
2164 ast_channel_lock(chan);
2165 ast_channel_datastore_add(chan, dial_cc_datastore);
2166 ast_channel_unlock(chan);
2167 cc_unref(monitor, "Unreffing allocation's reference");
2168 return 0;
2169}
static void cc_interface_tree_destroy(void *data)
Definition: ccss.c:1836
static int core_id_counter
Definition: ccss.c:120
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
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 1815 of file ccss.c.

1816{
1817 struct ast_cc_monitor *monitor = data;
1818 /* During the monitor creation process, it is possible for this
1819 * function to be called prior to when callbacks are assigned
1820 * to the monitor. Also, extension monitors do not have callbacks
1821 * assigned to them, so we wouldn't want to segfault when we try
1822 * to destroy one of them.
1823 */
1824 ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n",
1825 monitor->core_id, monitor->interface->device_name);
1828 }
1829 if (monitor->callbacks) {
1830 monitor->callbacks->destructor(monitor->private_data);
1831 }
1832 cc_unref(monitor->interface, "Unreffing tree's reference to interface");
1833 ast_free(monitor->dialstring);
1834}
static void cc_extension_monitor_destructor(void *private_data)
Definition: ccss.c:1799

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

3862{
3863 struct ast_cc_monitor_failure_data *failure_data = data;
3864 struct cc_core_instance *core_instance;
3865 struct ast_cc_monitor *monitor_iter;
3866
3867 core_instance = find_cc_core_instance(failure_data->core_id);
3868 if (!core_instance) {
3869 /* Core instance no longer exists or invalid core_id. */
3871 "Core %d: Could not find core instance for device %s '%s'\n",
3872 failure_data->core_id, failure_data->device_name, failure_data->debug);
3873 ast_free((char *) failure_data->device_name);
3874 ast_free((char *) failure_data->debug);
3875 ast_free(failure_data);
3876 return -1;
3877 }
3878
3879 AST_LIST_LOCK(core_instance->monitors);
3880 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3881 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3882 if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) {
3884 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3885 monitor_iter->interface->device_name, 1);
3886 monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id);
3887 cc_publish_monitorfailed(monitor_iter->core_id, monitor_iter->interface->device_name);
3888 cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference.");
3889 }
3890 }
3891 }
3893
3894 if (!has_device_monitors(core_instance)) {
3895 ast_cc_failed(core_instance->core_id, "All monitors have failed\n");
3896 }
3897 AST_LIST_UNLOCK(core_instance->monitors);
3898 cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n");
3899
3900 ast_free((char *) failure_data->device_name);
3901 ast_free((char *) failure_data->debug);
3902 ast_free(failure_data);
3903 return 0;
3904}
static void cc_publish_monitorfailed(int core_id, const char *callee)
Definition: ccss.c:1144

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

3706{
3707 va_list ap;
3708 int res;
3709
3710 va_start(ap, debug);
3711 res = cc_request_state_change(CC_CALLER_OFFERED, core_id, debug, ap);
3712 va_end(ap);
3713 return res;
3714}

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

4005{
4006 struct cc_core_instance *core_instance = data;
4007 int res = 0;
4008
4009 if (core_instance->agent->callbacks->party_b_free) {
4010 res = core_instance->agent->callbacks->party_b_free(core_instance->agent);
4011 }
4012 cc_unref(core_instance, "Party B free finished. Unref core_instance");
4013 return res;
4014}
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 1001 of file ccss.c.

1002{
1003 struct ast_json *blob;
1004 struct ast_json_payload *payload;
1005 struct stasis_message *message;
1006
1007 if (!message_type) {
1008 return -1;
1009 }
1010
1011 blob = ast_json_pack("{s: i}",
1012 "core_id", core_id);
1013 if (!blob) {
1014 return -1;
1015 }
1016
1017 if (extras) {
1018 ast_json_object_update(blob, extras);
1019 }
1020
1021 payload = ast_json_payload_create(blob);
1022 ast_json_unref(blob);
1023
1024 if (!payload) {
1025 return -1;
1026 }
1027
1028 message = stasis_message_create(message_type, payload);
1029 ao2_ref(payload, -1);
1030
1031 if (!message) {
1032 return -1;
1033 }
1034
1036 ao2_ref(message, -1);
1037
1038 return 0;
1039}
#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:1511
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 1041 of file ccss.c.

1042{
1043 struct ast_json *extras;
1044
1045 extras = ast_json_pack("{s: s, s: s}",
1046 "callee", callee,
1047 "service", service);
1048
1049 cc_publish(ast_cc_available_type(), core_id, extras);
1050 ast_json_unref(extras);
1051}
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1001
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 1110 of file ccss.c.

1111{
1112 struct ast_json *extras;
1113
1114 extras = ast_json_pack("{s: s}",
1115 "caller", caller);
1116
1117 cc_publish(ast_cc_callerrecalling_type(), core_id, extras);
1118 ast_json_unref(extras);
1119}
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 1099 of file ccss.c.

1100{
1101 struct ast_json *extras;
1102
1103 extras = ast_json_pack("{s: s}",
1104 "caller", caller);
1105
1107 ast_json_unref(extras);
1108}
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 1088 of file ccss.c.

1089{
1090 struct ast_json *extras;
1091
1092 extras = ast_json_pack("{s: s}",
1093 "caller", caller);
1094
1095 cc_publish(ast_cc_callerstopmonitoring_type(), core_id, extras);
1096 ast_json_unref(extras);
1097}
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 1132 of file ccss.c.

1133{
1134 struct ast_json *extras;
1135
1136 extras = ast_json_pack("{s: s, s: s}",
1137 "caller", caller,
1138 "reason", reason);
1139
1140 cc_publish(ast_cc_failure_type(), core_id, extras);
1141 ast_json_unref(extras);
1142}
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 1144 of file ccss.c.

1145{
1146 struct ast_json *extras;
1147
1148 extras = ast_json_pack("{s: s}",
1149 "callee", callee);
1150
1151 cc_publish(ast_cc_monitorfailed_type(), core_id, extras);
1152 ast_json_unref(extras);
1153}
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 1053 of file ccss.c.

1054{
1055 struct ast_json *extras;
1056
1057 extras = ast_json_pack("{s: s, s: I}",
1058 "caller", caller,
1059 "expires", (ast_json_int_t)expires);
1060
1061 cc_publish(ast_cc_offertimerstart_type(), core_id, extras);
1062 ast_json_unref(extras);
1063}
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 1121 of file ccss.c.

1122{
1123 struct ast_json *extras;
1124
1125 extras = ast_json_pack("{s: s}",
1126 "caller", caller);
1127
1128 cc_publish(ast_cc_recallcomplete_type(), core_id, extras);
1129 ast_json_unref(extras);
1130}
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 1077 of file ccss.c.

1078{
1079 struct ast_json *extras;
1080
1081 extras = ast_json_pack("{s: s}",
1082 "caller", caller);
1083
1084 cc_publish(ast_cc_requestacknowledged_type(), core_id, extras);
1085 ast_json_unref(extras);
1086}
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 1065 of file ccss.c.

1066{
1067 struct ast_json *extras;
1068
1069 extras = ast_json_pack("{s: s, s: s}",
1070 "caller", caller,
1071 "callee", callee);
1072
1073 cc_publish(ast_cc_requested_type(), core_id, extras);
1074 ast_json_unref(extras);
1075}
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 3359 of file ccss.c.

3360{
3361 struct cc_recall_ds_data *recall_data = data;
3362 recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree");
3363 ast_free(recall_data);
3364}

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

3346{
3347 struct cc_recall_ds_data *old_data = data;
3348 struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data));
3349
3350 if (!new_data) {
3351 return NULL;
3352 }
3353 new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate");
3354 new_data->core_id = old_data->core_id;
3355 new_data->nested = 1;
3356 return new_data;
3357}

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

3216{
3217 /* Both caller and callee are available, call agent's recall callback
3218 */
3219 cancel_available_timer(core_instance);
3220 cc_publish_callerrecalling(core_instance->core_id, core_instance->agent->device_name);
3221 return 0;
3222}
static void cancel_available_timer(struct cc_core_instance *core_instance)
Definition: ccss.c:3193
static void cc_publish_callerrecalling(int core_id, const char *caller)
Definition: ccss.c:1110

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

3296{
3297 int res;
3298 int debuglen;
3299 char dummy[1];
3300 va_list aq;
3301 struct cc_core_instance *core_instance;
3302 struct cc_state_change_args *args;
3303 /* This initial call to vsnprintf is simply to find what the
3304 * size of the string needs to be
3305 */
3306 va_copy(aq, ap);
3307 /* We add 1 to the result since vsnprintf's return does not
3308 * include the terminating null byte
3309 */
3310 debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1;
3311 va_end(aq);
3312
3313 if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) {
3314 return -1;
3315 }
3316
3318 if (!core_instance) {
3319 ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n",
3320 core_id);
3321 ast_free(args);
3322 return -1;
3323 }
3324
3325 args->core_instance = core_instance;
3326 args->state = state;
3327 args->core_id = core_id;
3328 vsnprintf(args->debug, debuglen, debug, ap);
3329
3331 if (res) {
3332 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3333 ast_free(args);
3334 }
3335 return res;
3336}
static int cc_do_state_change(void *datap)
Definition: ccss.c:3252
enum cc_state state
Definition: ccss.c:393
static void dummy(char *unused,...)
Definition: chan_unistim.c:220
struct cc_core_instance * core_instance
Definition: ccss.c:2962

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

413{
414 return cc_service_to_string_map[service].service_string;
415}
static const struct @319 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 584 of file ccss.c.

585{
587}
static enum ast_device_state cc_state_to_devstate_map[]
Definition: ccss.c:563

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

408{
409 return cc_state_to_string_map[state].state_string;
410}
static const struct @320 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 3941 of file ccss.c.

3942{
3943 struct cc_core_instance *core_instance= data;
3944 int res;
3945
3946 res = core_instance->agent->callbacks->status_request(core_instance->agent);
3947 cc_unref(core_instance, "Status request finished. Unref core instance");
3948 return res;
3949}
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 4037 of file ccss.c.

4038{
4039 struct cc_status_response_args *args = data;
4040 struct cc_core_instance *core_instance = args->core_instance;
4041 struct ast_cc_monitor *monitor_iter;
4042 enum ast_device_state devstate = args->devstate;
4043
4044 ast_free(args);
4045
4046 AST_LIST_LOCK(core_instance->monitors);
4047 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
4048 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR &&
4049 monitor_iter->callbacks->status_response) {
4050 monitor_iter->callbacks->status_response(monitor_iter, devstate);
4051 }
4052 }
4053 AST_LIST_UNLOCK(core_instance->monitors);
4054 cc_unref(core_instance, "Status response finished. Unref core instance");
4055 return 0;
4056}
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 3967 of file ccss.c.

3968{
3969 struct cc_core_instance *core_instance = data;
3970 int res = 0;
3971
3972 if (core_instance->agent->callbacks->stop_ringing) {
3973 res = core_instance->agent->callbacks->stop_ringing(core_instance->agent);
3974 }
3975 /* If an agent is being asked to stop ringing, then he needs to be prepared if for
3976 * whatever reason he needs to be called back again. The proper state to be in to
3977 * detect such a circumstance is the CC_ACTIVE state.
3978 *
3979 * We get to this state using the slightly unintuitive method of calling
3980 * ast_cc_monitor_request_acked because it gets us to the proper state.
3981 */
3982 ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.",
3983 core_instance->agent->device_name);
3984 cc_unref(core_instance, "Stop ringing finished. Unref core_instance");
3985 return res;
3986}
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 3524 of file ccss.c.

3525{
3526 char dialstring_search[AST_CHANNEL_NAME + 1];
3527
3528 if (ast_strlen_zero(dialstring)) {
3529 /* No dialstring to append. */
3530 return;
3531 }
3532 snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&');
3533 if (strstr(ast_str_buffer(*str), dialstring_search)) {
3534 return;
3535 }
3536 ast_str_append(str, 0, "%s", dialstring_search);
3537}
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 4273 of file ccss.c.

4274{
4275 struct cc_core_instance *core_instance;
4276 char device_name[AST_CHANNEL_NAME];
4277 unsigned long match_flags;
4278 int res;
4279
4280 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4281
4283 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) {
4284 ast_log_dynamic_level(cc_logger_level, "Cannot find CC transaction to cancel for caller %s\n", device_name);
4285 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4286 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NO_CORE_INSTANCE");
4287 return 0;
4288 }
4289
4290 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4291 ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calles with a generic agent\n");
4292 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4293 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4294 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NOT_GENERIC");
4295 return 0;
4296 }
4297 res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s",
4298 core_instance->core_id, device_name);
4299 cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4300 pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", res ? "FAIL" : "SUCCESS");
4301 if (res) {
4302 pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "UNSPECIFIED");
4303 }
4304 return 0;
4305}
#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:469
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:492

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

4223{
4224 struct cc_core_instance *core_instance;
4225 char device_name[AST_CHANNEL_NAME];
4226 unsigned long match_flags;
4227 int res;
4228
4229 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4230
4232 if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) {
4233 ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name);
4234 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4235 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NO_CORE_INSTANCE");
4236 return 0;
4237 }
4238
4239 ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n",
4240 core_instance->core_id, device_name);
4241
4242 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4243 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n",
4244 core_instance->core_id);
4245 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4246 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NOT_GENERIC");
4247 cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent");
4248 return 0;
4249 }
4250
4252 ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n",
4253 core_instance->core_id);
4254 ast_cc_failed(core_instance->core_id, "Too many CC requests\n");
4255 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4256 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "TOO_MANY_REQUESTS");
4257 cc_unref(core_instance, "Unref core_instance since too many CC requests");
4258 return 0;
4259 }
4260
4261 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);
4262 pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS");
4263 if (res) {
4264 pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "UNSPECIFIED");
4265 }
4266
4267 cc_unref(core_instance, "Done with CallCompletionRequest");
4268 return 0;
4269}
int ast_cc_agent_accept_request(int core_id, const char *const debug,...)
Accept inbound CC request.
Definition: ccss.c:3741

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

601{
602 struct cc_core_instance *core_instance;
603 unsigned long match_flags;
604 enum ast_device_state cc_current_state;
605
608 (char *) device_name, &match_flags,
609 "Find Core Instance for ccss_device_state reqeust.");
610 if (!core_instance) {
612 "Couldn't find a core instance for caller %s\n", device_name);
614 }
615
617 "Core %d: Found core_instance for caller %s in state %s\n",
618 core_instance->core_id, device_name, cc_state_to_string(core_instance->current_state));
619
620 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
622 "Core %d: Device State is only for generic agent types.\n",
623 core_instance->core_id);
624 cc_unref(core_instance, "Unref core_instance since ccss_device_state was called with native agent");
626 }
627 cc_current_state = cc_state_to_devstate(core_instance->current_state);
628 cc_unref(core_instance, "Unref core_instance done with ccss_device_state");
629 return cc_current_state;
630}
static enum ast_device_state cc_state_to_devstate(enum cc_state state)
Definition: ccss.c:584

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

642{
643 enum ast_device_state devstate;
644
645 devstate = cc_state_to_devstate(state);
646
648 "Notification of CCSS state change to '%s', device state '%s' for device '%s'\n",
649 cc_state_to_string(state), ast_devstate2str(devstate), device);
650
651 ast_devstate_changed(devstate, AST_DEVSTATE_CACHABLE, "ccss:%s", device);
652}
@ 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.
Definition: devicestate.c:510
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237

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

2511{
2512 ast_assert(callbacks->init != NULL);
2513 ast_assert(callbacks->start_offer_timer != NULL);
2514 ast_assert(callbacks->stop_offer_timer != NULL);
2515 ast_assert(callbacks->respond != NULL);
2516 ast_assert(callbacks->status_request != NULL);
2517 ast_assert(callbacks->start_monitoring != NULL);
2518 ast_assert(callbacks->callee_available != NULL);
2519 ast_assert(callbacks->destructor != NULL);
2520}

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

4521{
4522 int wordlen = strlen(word);
4523 struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0);
4524 struct cc_core_instance *core_instance;
4525
4526 for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance"));
4527 cc_unref(core_instance, "CLI tab completion iteration")) {
4528 char core_id_str[20];
4529 snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id);
4530 if (!strncmp(word, core_id_str, wordlen)) {
4531 if (ast_cli_completion_add(ast_strdup(core_id_str))) {
4532 cc_unref(core_instance, "Found a matching core ID for CLI tab-completion");
4533 break;
4534 }
4535 }
4536 }
4537 ao2_iterator_destroy(&core_iter);
4538
4539 return NULL;
4540}
#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:2756
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 2484 of file ccss.c.

2485{
2487
2488 ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents");
2489 ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count);
2490 return data.count;
2491}
static int count_agents_cb(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:530
int core_id_exception
Definition: ccss.c:519

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

531{
532 struct cc_core_instance *core_instance = obj;
533 const char *name = arg;
534 struct count_agents_cb_data *cb_data = data;
535
536 if (cb_data->core_id_exception == core_instance->core_id) {
537 ast_log_dynamic_level(cc_logger_level, "Found agent with core_id %d but not counting it toward total\n", core_instance->core_id);
538 return 0;
539 }
540
541 if (core_instance->current_state >= CC_CALLER_REQUESTED && !strcmp(core_instance->agent->device_name, name)) {
542 cb_data->count++;
543 }
544 return 0;
545}

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

4314{
4315 struct cc_core_instance *core_instance = obj;
4316 struct count_monitors_cb_data *cb_data = arg;
4317 const char *device_name = cb_data->device_name;
4318 const char *monitor_type = cb_data->monitor_type;
4319 struct ast_cc_monitor *monitor_iter;
4320
4321 AST_LIST_LOCK(core_instance->monitors);
4322 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
4323 if (!strcmp(monitor_iter->interface->device_name, device_name) &&
4324 !strcmp(monitor_iter->interface->monitor_type, monitor_type)) {
4325 cb_data->count++;
4326 break;
4327 }
4328 }
4329 AST_LIST_UNLOCK(core_instance->monitors);
4330 return 0;
4331}
const char * monitor_type
Definition: ccss.c:4309

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

1388{
1389 struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list),
1390 generic_monitor_instance_list_destructor, "allocate generic monitor instance list");
1391 char * device_name;
1392 struct stasis_topic *device_specific_topic;
1393
1394 if (!generic_list) {
1395 return NULL;
1396 }
1397
1398 if (!(device_name = ast_strdup(monitor->interface->device_name))) {
1399 cc_unref(generic_list, "Failed to strdup the monitor's device name");
1400 return NULL;
1401 }
1402 ast_tech_to_upper(device_name);
1403 generic_list->device_name = device_name;
1404
1405 device_specific_topic = ast_device_state_topic(device_name);
1406 if (!device_specific_topic) {
1407 return NULL;
1408 }
1409
1410 if (!(generic_list->sub = stasis_subscribe(device_specific_topic, generic_monitor_devstate_cb, NULL))) {
1411 cc_unref(generic_list, "Failed to subscribe to device state");
1412 return NULL;
1413 }
1416 generic_list->current_state = ast_device_state(monitor->interface->device_name);
1417 ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list");
1418 return generic_list;
1419}
static void generic_monitor_instance_list_destructor(void *obj)
Definition: ccss.c:1374
static void generic_monitor_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: ccss.c:1462
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:1339
const char * device_name
Definition: ccss.c:1321

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

1923{
1924 struct dialed_cc_interfaces *cc_interfaces = data;
1925 cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree");
1926 ast_free(cc_interfaces);
1927}

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

1943{
1944 struct dialed_cc_interfaces *old_cc_interfaces = data;
1945 struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces));
1946 if (!new_cc_interfaces) {
1947 return NULL;
1948 }
1949 new_cc_interfaces->ignore = old_cc_interfaces->ignore;
1950 new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id;
1951 new_cc_interfaces->is_original_caller = 0;
1952 cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree");
1953 new_cc_interfaces->core_id = old_cc_interfaces->core_id;
1954 new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree;
1955 return new_cc_interfaces;
1956}

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

1974{
1975 struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt));
1976 if (!ext_pvt) {
1977 return NULL;
1978 }
1980 return ext_pvt;
1981}
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681

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

1248{
1249 struct cc_agent_backend *backend;
1250 const struct ast_cc_agent_callbacks *callbacks = NULL;
1251 struct ast_cc_config_params *cc_params;
1252 char type[32];
1253
1254 cc_params = ast_channel_get_cc_config_params(chan);
1255 if (!cc_params) {
1256 return NULL;
1257 }
1258 switch (ast_get_cc_agent_policy(cc_params)) {
1260 ast_copy_string(type, "generic", sizeof(type));
1261 break;
1263 ast_channel_get_cc_agent_type(chan, type, sizeof(type));
1264 break;
1265 default:
1266 ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n");
1267 return NULL;
1268 }
1269
1271 AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) {
1272 if (!strcmp(backend->callbacks->type, type)) {
1273 ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type);
1274 callbacks = backend->callbacks;
1275 break;
1276 }
1277 }
1279 return callbacks;
1280}
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:10513
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494

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

1365{
1366 struct generic_monitor_instance_list finder = {0};
1367 char *uppertech = ast_strdupa(device_name);
1368 ast_tech_to_upper(uppertech);
1369 finder.device_name = uppertech;
1370
1371 return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list");
1372}
#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 1178 of file ccss.c.

1179{
1180 struct cc_monitor_backend *backend;
1181 const struct ast_cc_monitor_callbacks *callbacks = NULL;
1182
1184 AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) {
1185 if (!strcmp(backend->callbacks->type, type)) {
1186 ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type);
1187 callbacks = backend->callbacks;
1188 break;
1189 }
1190 }
1192 return callbacks;
1193}
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 2739 of file ccss.c.

2740{
2741 struct ast_cc_agent *agent = userdata;
2742 enum ast_device_state new_state;
2743 struct ast_device_state_message *dev_state;
2744 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2745
2747 cc_unref(agent, "Done holding ref for subscription");
2748 return;
2750 return;
2751 }
2752
2753 dev_state = stasis_message_data(msg);
2754 if (dev_state->eid) {
2755 /* ignore non-aggregate states */
2756 return;
2757 }
2758
2759 new_state = dev_state->state;
2760 if (!cc_generic_is_device_available(new_state)) {
2761 /* Not interested in this new state of the device. It is still busy. */
2762 return;
2763 }
2764
2765 generic_pvt->sub = stasis_unsubscribe(sub);
2766 ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name);
2767}
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:3785
struct stasis_forward * sub
Definition: res_corosync.c:240
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
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:1174
The structure that contains device state.
Definition: devicestate.h:238
enum ast_device_state state
Definition: devicestate.h:248
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:246

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_message_type(), 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 1462 of file ccss.c.

1463{
1464 /* Wow, it's cool that we've picked up on a state change, but we really want
1465 * the actual work to be done in the core's taskprocessor execution thread
1466 * so that all monitor operations can be serialized. Locks?! We don't need
1467 * no steenkin' locks!
1468 */
1469 struct ast_device_state_message *dev_state;
1471 return;
1472 }
1473
1474 dev_state = stasis_message_data(msg);
1475 if (dev_state->eid) {
1476 /* ignore non-aggregate states */
1477 return;
1478 }
1479
1480 ao2_t_ref(dev_state, +1, "Bumping dev_state ref for cc_core_taskprocessor");
1482 ao2_cleanup(dev_state);
1483 return;
1484 }
1485}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
static int generic_monitor_devstate_tp_cb(void *data)
Definition: ccss.c:1421

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(), stasis_message_data(), and stasis_message_type().

Referenced by create_new_generic_list().

◆ generic_monitor_devstate_tp_cb()

static int generic_monitor_devstate_tp_cb ( void *  data)
static

Definition at line 1421 of file ccss.c.

1422{
1423 RAII_VAR(struct ast_device_state_message *, dev_state, data, ao2_cleanup);
1424 enum ast_device_state new_state = dev_state->state;
1425 enum ast_device_state previous_state;
1426 struct generic_monitor_instance_list *generic_list;
1427 struct generic_monitor_instance *generic_instance;
1428
1429 if (!(generic_list = find_generic_monitor_instance_list(dev_state->device))) {
1430 /* The most likely cause for this is that we destroyed the monitor in the
1431 * time between subscribing to its device state and the time this executes.
1432 * Not really a big deal.
1433 */
1434 return 0;
1435 }
1436
1437 if (generic_list->current_state == new_state) {
1438 /* The device state hasn't actually changed, so we don't really care */
1439 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1440 return 0;
1441 }
1442
1443 previous_state = generic_list->current_state;
1444 generic_list->current_state = new_state;
1445
1446 if (cc_generic_is_device_available(new_state) &&
1447 (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE ||
1448 previous_state == AST_DEVICE_BUSY)) {
1449 AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1450 if (!generic_instance->is_suspended && generic_instance->monitoring) {
1451 generic_instance->monitoring = 0;
1452 generic_list->fit_for_recall = 1;
1453 ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1454 break;
1455 }
1456 }
1457 }
1458 cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1459 return 0;
1460}
@ 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:941

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

1375{
1376 struct generic_monitor_instance_list *generic_list = obj;
1377 struct generic_monitor_instance *generic_instance;
1378
1379 generic_list->sub = stasis_unsubscribe(generic_list->sub);
1380 while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) {
1381 ast_free(generic_instance);
1382 }
1383 ast_free((char *)generic_list->device_name);
1384}

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

2795{
2796 struct ast_cc_agent *agent = data;
2797 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2798 const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name));
2799 const char *tech;
2800 char *target;
2801 int reason;
2802 struct ast_channel *chan;
2803 const char *callback_sub = ast_get_cc_callback_sub(agent->cc_params);
2804 unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
2806
2807 if (!tmp_cap) {
2808 return NULL;
2809 }
2810
2811 tech = interface;
2812 if ((target = strchr(interface, '/'))) {
2813 *target++ = '\0';
2814 }
2815
2817 if (!(chan = ast_request_and_dial(tech, tmp_cap, NULL, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
2818 /* Hmm, no channel. Sucks for you, bud.
2819 */
2820 ast_log_dynamic_level(cc_logger_level, "Core %u: Failed to call back %s for reason %d\n",
2821 agent->core_id, agent->device_name, reason);
2822 ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target);
2823 ao2_ref(tmp_cap, -1);
2824 return NULL;
2825 }
2826 ao2_ref(tmp_cap, -1);
2827
2828 /* We have a channel. It's time now to set up the datastore of recalled CC interfaces.
2829 * This will be a common task for all recall functions. If it were possible, I'd have
2830 * the core do it automatically, but alas I cannot. Instead, I will provide a public
2831 * function to do so.
2832 */
2835
2836 ast_channel_exten_set(chan, generic_pvt->exten);
2837 ast_channel_context_set(chan, generic_pvt->context);
2838 ast_channel_priority_set(chan, 1);
2839
2840 pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten);
2841 pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context);
2842
2843 if (!ast_strlen_zero(callback_sub)) {
2844 ast_log_dynamic_level(cc_logger_level, "Core %u: There's a callback subroutine configured for agent %s\n",
2845 agent->core_id, agent->device_name);
2846 if (ast_app_exec_sub(NULL, chan, callback_sub, 0)) {
2847 ast_cc_failed(agent->core_id, "Callback subroutine to %s failed. Maybe a hangup?", agent->device_name);
2848 ast_hangup(chan);
2849 return NULL;
2850 }
2851 }
2852 if (ast_pbx_start(chan)) {
2853 ast_cc_failed(agent->core_id, "PBX failed to start for %s.", agent->device_name);
2854 ast_hangup(chan);
2855 return NULL;
2856 }
2857 ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling",
2858 agent->device_name);
2859 return NULL;
2860}
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:3372
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:3796
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:3596
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:2541
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:6174
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.
Definition: format_cache.c:41
@ 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:4708
#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 4542 of file ccss.c.

4543{
4544 switch (cmd) {
4545 case CLI_INIT:
4546 e->command = "cc cancel [core|all]";
4547 e->usage =
4548 "Usage: cc cancel can be used in two ways.\n"
4549 " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n"
4550 " core ID equal to the specified core ID.\n"
4551 " 2. 'cc cancel all' will cancel all active CC transactions.\n";
4552 return NULL;
4553 case CLI_GENERATE:
4554 if (a->pos == 3 && !strcasecmp(a->argv[2], "core")) {
4555 return complete_core_id(a->word);
4556 }
4557 return NULL;
4558 }
4559
4560 if (a->argc == 4) {
4561 int core_id;
4562 char *endptr;
4563 if (strcasecmp(a->argv[2], "core")) {
4564 return CLI_SHOWUSAGE;
4565 }
4566 core_id = strtol(a->argv[3], &endptr, 10);
4567 if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) {
4568 return CLI_SHOWUSAGE;
4569 }
4570 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id");
4571 } else if (a->argc == 3) {
4572 if (strcasecmp(a->argv[2], "all")) {
4573 return CLI_SHOWUSAGE;
4574 }
4575 ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores");
4576 } else {
4577 return CLI_SHOWUSAGE;
4578 }
4579
4580 return CLI_SUCCESS;
4581}
static int kill_cores(void *obj, void *arg, int flags)
Definition: ccss.c:4509
static char * complete_core_id(const char *word)
Definition: ccss.c:4520
#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 4476 of file ccss.c.

4477{
4478 int *cli_fd;
4479
4480 switch (cmd) {
4481 case CLI_INIT:
4482 e->command = "cc report status";
4483 e->usage =
4484 "Usage: cc report status\n"
4485 " Report the current status of any ongoing CC transactions\n";
4486 return NULL;
4487 case CLI_GENERATE:
4488 return NULL;
4489 }
4490
4491 if (a->argc != 3) {
4492 return CLI_SHOWUSAGE;
4493 }
4494
4495 cli_fd = ast_malloc(sizeof(*cli_fd));
4496 if (!cli_fd) {
4497 return CLI_FAILURE;
4498 }
4499
4500 *cli_fd = a->fd;
4501
4503 ast_free(cli_fd);
4504 return CLI_FAILURE;
4505 }
4506 return CLI_SUCCESS;
4507}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
static int cc_cli_output_status(void *data)
Definition: ccss.c:4459
#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 3060 of file ccss.c.

3061{
3062 struct ast_cc_monitor *iter;
3063 int res = 0;
3064
3065 AST_LIST_TRAVERSE(core_instance->monitors, iter, next) {
3067 res = 1;
3068 break;
3069 }
3070 }
3071
3072 return res;
3073}

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 ( void  )
static

Definition at line 4401 of file ccss.c.

4402{
4403 struct ast_config *cc_config;
4404 struct ast_flags config_flags = { 0, };
4405
4406 cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
4407 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
4409 "Could not find valid ccss.conf file. Using cc_[state]_devstate defaults\n");
4410 return;
4411 }
4412
4413 initialize_cc_devstate_map_helper(cc_config, CC_AVAILABLE, "cc_available_devstate");
4414 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_OFFERED, "cc_caller_offered_devstate");
4415 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_REQUESTED, "cc_caller_requested_devstate");
4416 initialize_cc_devstate_map_helper(cc_config, CC_ACTIVE, "cc_active_devstate");
4417 initialize_cc_devstate_map_helper(cc_config, CC_CALLEE_READY, "cc_callee_ready_devstate");
4418 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_BUSY, "cc_caller_busy_devstate");
4419 initialize_cc_devstate_map_helper(cc_config, CC_RECALLING, "cc_recalling_devstate");
4420 initialize_cc_devstate_map_helper(cc_config, CC_COMPLETE, "cc_complete_devstate");
4421 initialize_cc_devstate_map_helper(cc_config, CC_FAILED, "cc_failed_devstate");
4422
4423 ast_config_destroy(cc_config);
4424}
static void initialize_cc_devstate_map_helper(struct ast_config *cc_config, enum cc_state state, const char *cc_setting)
Definition: ccss.c:4377
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3321
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
Structure used to handle boolean flags.
Definition: utils.h:199

References ast_config_destroy(), ast_config_load2(), ast_log, CC_ACTIVE, CC_AVAILABLE, CC_CALLEE_READY, CC_CALLER_BUSY, CC_CALLER_OFFERED, CC_CALLER_REQUESTED, CC_COMPLETE, CC_FAILED, CC_RECALLING, CONFIG_STATUS_FILEINVALID, initialize_cc_devstate_map_helper(), and LOG_WARNING.

Referenced by load_module().

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

4378{
4379 const char *cc_devstate_str;
4380 enum ast_device_state this_devstate;
4381
4382 if ((cc_devstate_str = ast_variable_retrieve(cc_config, "general", cc_setting))) {
4383 this_devstate = ast_devstate_val(cc_devstate_str);
4384 if (this_devstate != AST_DEVICE_UNKNOWN) {
4385 cc_state_to_devstate_map[state] = this_devstate;
4386 }
4387 }
4388}
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
Definition: devicestate.c:260
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783

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 ( void  )
static

Definition at line 4342 of file ccss.c.

4343{
4344 struct ast_config *cc_config;
4345 const char *cc_max_requests_str;
4346 struct ast_flags config_flags = {0,};
4347 char *endptr;
4348
4349 cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
4350 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
4351 ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests default\n");
4353 return;
4354 }
4355
4356 if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) {
4357 ast_config_destroy(cc_config);
4359 return;
4360 }
4361
4362 global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10);
4363
4364 if (!ast_strlen_zero(endptr)) {
4365 ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n");
4367 }
4368
4369 ast_config_destroy(cc_config);
4370 return;
4371}
#define GLOBAL_CC_MAX_REQUESTS_DEFAULT
Definition: ccss.c:660

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

Referenced by load_module().

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

2969{
2970 int is_valid = 0;
2971 switch (new_state) {
2972 case CC_AVAILABLE:
2973 ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to state %u? That should never happen.\n",
2974 agent->core_id, new_state);
2975 break;
2976 case CC_CALLER_OFFERED:
2977 if (current_state == CC_AVAILABLE) {
2978 is_valid = 1;
2979 }
2980 break;
2982 if (current_state == CC_CALLER_OFFERED ||
2983 (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) {
2984 is_valid = 1;
2985 }
2986 break;
2987 case CC_ACTIVE:
2988 if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) {
2989 is_valid = 1;
2990 }
2991 break;
2992 case CC_CALLEE_READY:
2993 if (current_state == CC_ACTIVE) {
2994 is_valid = 1;
2995 }
2996 break;
2997 case CC_CALLER_BUSY:
2998 if (current_state == CC_CALLEE_READY) {
2999 is_valid = 1;
3000 }
3001 break;
3002 case CC_RECALLING:
3003 if (current_state == CC_CALLEE_READY) {
3004 is_valid = 1;
3005 }
3006 break;
3007 case CC_COMPLETE:
3008 if (current_state == CC_RECALLING) {
3009 is_valid = 1;
3010 }
3011 break;
3012 case CC_FAILED:
3013 is_valid = 1;
3014 break;
3015 default:
3016 ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to unknown state %u\n",
3017 agent->core_id, new_state);
3018 break;
3019 }
3020
3021 return is_valid;
3022}
#define ast_test_flag(p, flag)
Definition: utils.h:63

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

4510{
4511 int *core_id = arg;
4512 struct cc_core_instance *core_instance = obj;
4513
4514 if (!core_id || (core_instance->core_id == *core_id)) {
4515 ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n");
4516 }
4517 return 0;
4518}

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

2494{
2495 unsigned long match_flags = MATCH_NO_REQUEST;
2496 struct ao2_iterator *dups_iter;
2497
2498 /*
2499 * Must remove the ref that was in cc_core_instances outside of
2500 * the container lock to prevent deadlock.
2501 */
2503 match_agent, caller, &match_flags, "Killing duplicate offers");
2504 if (dups_iter) {
2505 /* Now actually unref any duplicate offers by simply destroying the iterator. */
2506 ao2_iterator_destroy(dups_iter);
2507 }
2508}
@ 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_module()

static int load_module ( void  )
static

Definition at line 4618 of file ccss.c.

4619{
4620 int res;
4621
4625 "Create core instance container");
4626 if (!cc_core_instances) {
4628 }
4629
4632 generic_monitor_instance_list_hash_fn, NULL, generic_monitor_instance_list_cmp_fn,
4633 "Create generic monitor container");
4634 if (!generic_monitors) {
4636 }
4639 }
4642 }
4645 }
4650
4655
4656 /* Read the map and register the device state callback for generic agents */
4659
4661}
@ 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 void initialize_cc_devstate_map(void)
Definition: ccss.c:4401
static enum ast_device_state ccss_device_state(const char *device_name)
Definition: ccss.c:600
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition: ccss.c:1162
static const int CC_CORE_INSTANCES_BUCKETS
Definition: ccss.c:325
static const char * ccreq_app
Definition: ccss.c:4220
static int cccancel_exec(struct ast_channel *chan, const char *data)
Definition: ccss.c:4273
static const char * cccancel_app
Definition: ccss.c:4271
static int cc_core_instance_cmp_fn(void *obj, void *arg, int flags)
Definition: ccss.c:423
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:1217
static const char * CC_LOGGER_LEVEL_NAME
Definition: ccss.c:129
static struct ast_cc_monitor_callbacks generic_monitor_cbs
Definition: ccss.c:1302
static int ccreq_exec(struct ast_channel *chan, const char *data)
Definition: ccss.c:4222
static void initialize_cc_max_requests(void)
Definition: ccss.c:4342
static struct ast_cli_entry cc_cli[]
Definition: ccss.c:4583
static int cc_core_instance_hash_fn(const void *obj, const int flags)
Definition: ccss.c:417
static struct ast_cc_agent_callbacks generic_agent_callbacks
Definition: ccss.c:2584
#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.
Definition: devicestate.c:391
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:2839
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:103
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition: module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
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
Definition: taskprocessor.h:76
#define ARRAY_LEN(a)
Definition: utils.h:666

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_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, initialize_cc_devstate_map(), initialize_cc_max_requests(), NULL, and TPS_REF_DEFAULT.

◆ match_agent()

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

Definition at line 492 of file ccss.c.

493{
494 struct cc_core_instance *core_instance = obj;
495 const char *name = arg;
496 unsigned long match_flags = *(unsigned long *)data;
497 int possible_match = 0;
498
500 possible_match = 1;
501 }
502
503 if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) {
504 possible_match = 1;
505 }
506
507 if (!possible_match) {
508 return 0;
509 }
510
511 if (!strcmp(core_instance->agent->device_name, name)) {
512 return CMP_MATCH | CMP_STOP;
513 }
514 return 0;
515}

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

743{
744 switch (policy) {
746 return "never";
748 return "native";
750 return "generic";
752 return "always";
753 default:
754 /* This should never happen... */
755 return "";
756 }
757}
@ 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 2669 of file ccss.c.

2670{
2671 struct ast_cc_agent *agent = (struct ast_cc_agent *) data;
2673 ast_log_dynamic_level(cc_logger_level, "Core %u: Queuing change request because offer timer has expired.\n",
2674 agent->core_id);
2675 agent_pvt->offer_timer_id = -1;
2676 ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name);
2677 cc_unref(agent, "Remove scheduler's reference to the agent");
2678 return 0;
2679}

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

4447{
4448 int *cli_fd = arg;
4449 struct cc_core_instance *core_instance = obj;
4450
4451 ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name,
4452 cc_state_to_string(core_instance->current_state));
4453 AST_LIST_LOCK(core_instance->monitors);
4454 cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0);
4455 AST_LIST_UNLOCK(core_instance->monitors);
4456 return 0;
4457}

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

3076{
3077 struct ast_cc_monitor *monitor_iter;
3078 AST_LIST_LOCK(core_instance->monitors);
3079 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3080 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3081 if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) {
3083 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3084 monitor_iter->interface->device_name, 1);
3085 cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor");
3086 } else {
3087 cc_publish_requested(core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name);
3088 }
3089 }
3090 }
3092
3093 if (!has_device_monitors(core_instance)) {
3094 ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC");
3095 }
3096 AST_LIST_UNLOCK(core_instance->monitors);
3097}
static void cc_publish_requested(int core_id, const char *caller, const char *callee)
Definition: ccss.c:1065
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 697 of file ccss.c.

698{
699 if (!strcasecmp(value, "never")) {
700 return AST_CC_AGENT_NEVER;
701 } else if (!strcasecmp(value, "native")) {
702 return AST_CC_AGENT_NATIVE;
703 } else if (!strcasecmp(value, "generic")) {
705 } else {
706 ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value);
707 return AST_CC_AGENT_NEVER;
708 }
709}

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

712{
713 if (!strcasecmp(value, "never")) {
715 } else if (!strcasecmp(value, "native")) {
717 } else if (!strcasecmp(value, "generic")) {
719 } else if (!strcasecmp(value, "always")) {
721 } else {
722 ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value);
724 }
725}

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

3161{
3162 struct ast_cc_monitor *monitor_iter;
3163 AST_LIST_LOCK(core_instance->monitors);
3164 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3165 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3166 if (monitor_iter->callbacks->suspend(monitor_iter)) {
3168 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3169 monitor_iter->interface->device_name, 1);
3170 cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor");
3171 }
3172 }
3173 }
3175
3176 if (!has_device_monitors(core_instance)) {
3177 ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC");
3178 }
3179 AST_LIST_UNLOCK(core_instance->monitors);
3180}
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 4588 of file ccss.c.

4589{
4590 ast_devstate_prov_del("ccss");
4597
4598 if (cc_sched_context) {
4601 }
4604 }
4605 /* Note that core instances must be destroyed prior to the generic_monitors */
4606 if (cc_core_instances) {
4607 ao2_t_ref(cc_core_instances, -1, "Unref cc_core_instances container in cc_shutdown");
4609 }
4610 if (generic_monitors) {
4611 ao2_t_ref(generic_monitors, -1, "Unref generic_monitor container in cc_shutdown");
4613 }
4614
4615 return 0;
4616}
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1195
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1232
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:418
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:2897
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, and NULL.

◆ unsuspend()

static void unsuspend ( struct cc_core_instance core_instance)
static

Definition at line 3113 of file ccss.c.

3114{
3115 struct ast_cc_monitor *monitor_iter;
3116 AST_LIST_LOCK(core_instance->monitors);
3117 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3118 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3119 if (monitor_iter->callbacks->unsuspend(monitor_iter)) {
3121 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3122 monitor_iter->interface->device_name, 1);
3123 cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor");
3124 }
3125 }
3126 }
3128
3129 if (!has_device_monitors(core_instance)) {
3130 ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC");
3131 }
3132 AST_LIST_UNLOCK(core_instance->monitors);
3133}
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 = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CORE, }
static

Definition at line 4668 of file ccss.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4668 of file ccss.c.

◆ cc_agent_backends

struct cc_agent_backends cc_agent_backends = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }

◆ 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:4542
static char * handle_cc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: ccss.c:4476

Definition at line 4583 of file ccss.c.

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

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

Referenced by load_module(), and unload_module().

◆ cc_monitor_backends

struct cc_monitor_backends cc_monitor_backends = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }

◆ cc_request_count

int cc_request_count
static

The current number of CC requests in the system

Definition at line 141 of file ccss.c.

Referenced by ast_cc_request_is_within_limits().

◆ cc_sched_context

struct ast_sched_context* cc_sched_context
static

◆ 

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

Referenced by cc_state_to_devstate(), and initialize_cc_devstate_map_helper().

◆ 

const struct { ... } cc_state_to_string_map[]

Referenced by cc_state_to_string().

◆ cccancel_app

const char* cccancel_app = "CallCompletionCancel"
static

Definition at line 4271 of file ccss.c.

Referenced by load_module(), and unload_module().

◆ ccreq_app

const char* ccreq_app = "CallCompletionRequest"
static

Definition at line 4220 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 120 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 1853 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:1922
static void * dialed_cc_interfaces_duplicate(void *data)
Definition: ccss.c:1942

Definition at line 1967 of file ccss.c.

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

◆ generic_agent_callbacks

struct ast_cc_agent_callbacks generic_agent_callbacks
static

Definition at line 2584 of file ccss.c.

Referenced by load_module(), and unload_module().

◆ generic_monitor_cbs

struct ast_cc_monitor_callbacks generic_monitor_cbs
static

Definition at line 1302 of file ccss.c.

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

Referenced by ast_cc_request_is_within_limits(), and initialize_cc_max_requests().

◆ 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:3359
static void * cc_recall_ds_duplicate(void *data)
Definition: ccss.c:3345

Definition at line 3366 of file ccss.c.

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

◆ service

enum ast_cc_service_type service

◆ service_string

const char* service_string

Definition at line 384 of file ccss.c.

◆ state

Definition at line 393 of file ccss.c.

Referenced by __state_find_or_add(), action_presencestate(), ami_outbound_registration_task(), ami_register(), ami_unregister(), apply_negotiated_sdp_stream(), ast_bucket_alloc(), ast_bucket_file_alloc(), ast_channel_get_t38_state(), ast_channel_start_silence_generator(), ast_complete_channels(), ast_devstate_aggregate_add(), ast_devstate_str(), ast_dns_get_nameservers(), ast_endpoint_set_state(), ast_extension_state3(), ast_speech_change_state(), ast_stream_set_state(), auth_observer(), bucket_file_wizard_retrieve(), bucket_wizard_retrieve(), calendarstate(), cc_request_state_change(), cc_state_to_devstate(), cc_state_to_string(), chan_pjsip_devicestate(), chan_pjsip_queryoption(), cli_register(), cli_show_monitors(), cli_unregister(), complete_agent(), complete_agent_logoff(), complete_meetmecmd_list(), complete_meetmecmd_mute_kick(), complete_voicemail_move_message(), create_outgoing_sdp_stream(), custom_presence_callback(), decode(), defer_incoming_sdp_stream(), destroy_all_channels(), device_state_alloc(), device_state_cb(), device_state_notify_callbacks(), devstate_cached(), dialog_info_generate_body_content(), do_state_change(), extensionstate2devicestate(), find_or_create_temporary_state(), find_state_by_transport(), find_temporary_state(), gen_alloc(), get_state(), handle_cli_devstate_change(), handle_cli_presencestate_change(), handle_cli_presencestate_list(), handle_hint_change_message_type(), handle_logger_set_level(), hfp_parse_cind(), hfp_parse_cind_test(), hfp_parse_cmgr(), hook_off(), hook_re_enable(), hook_state_alloc(), init_hook(), initialize_cc_devstate_map_helper(), jingle_endpoint_state_create(), load_module(), media_offer_read_av(), media_offer_write_av(), mkintf(), moh_alloc(), moh_files_alloc(), moh_files_generator(), moh_files_release(), moh_release(), monitor_dial(), negotiate_incoming_sdp_stream(), ooh323_queryoption(), poll_mailbox(), presence_read(), presence_write(), publish_device_state_to_stasis(), recording_set_state(), refer_progress_notification_alloc(), refresh_write_cb(), registration_transport_shutdown_cb(), remove_temporary_state(), session_refresh_state_get_or_alloc(), set_state(), sip_options_get_endpoint_state_compositor_state(), sip_outbound_publish_state_alloc(), sip_outbound_publish_synchronize(), sip_outbound_registration_state_alloc(), sla_change_trunk_state(), stasis_app_device_state_update(), stasis_state_publish_by_id(), stasis_state_topic(), state_alloc(), t38_reinvite_response_cb(), t38_reinvite_sdp_cb(), t38_state_get_or_alloc(), transport_tls_verify(), worker_set_state(), xmpp_client_change_state(), xmpp_pubsub_publish_device_state(), and xmpp_show_clients().

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

Referenced by cc_do_state_change().

◆ state_string

const char* state_string

Definition at line 394 of file ccss.c.