Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 558 of file ccss.c.

◆ CC_AVAILABLE_DEVSTATE_DEFAULT

#define CC_AVAILABLE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 555 of file ccss.c.

◆ CC_CALLEE_READY_DEVSTATE_DEFAULT

#define CC_CALLEE_READY_DEVSTATE_DEFAULT   AST_DEVICE_RINGING

Definition at line 559 of file ccss.c.

◆ CC_CALLER_BUSY_DEVSTATE_DEFAULT

#define CC_CALLER_BUSY_DEVSTATE_DEFAULT   AST_DEVICE_ONHOLD

Definition at line 560 of file ccss.c.

◆ CC_CALLER_OFFERED_DEVSTATE_DEFAULT

#define CC_CALLER_OFFERED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 556 of file ccss.c.

◆ CC_CALLER_REQUESTED_DEVSTATE_DEFAULT

#define CC_CALLER_REQUESTED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 557 of file ccss.c.

◆ CC_COMPLETE_DEVSTATE_DEFAULT

#define CC_COMPLETE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 562 of file ccss.c.

◆ CC_FAILED_DEVSTATE_DEFAULT

#define CC_FAILED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 563 of file ccss.c.

◆ CC_MAX_AGENTS_DEFAULT

#define CC_MAX_AGENTS_DEFAULT   5

Definition at line 664 of file ccss.c.

◆ CC_MAX_MONITORS_DEFAULT

#define CC_MAX_MONITORS_DEFAULT   5

Definition at line 665 of file ccss.c.

◆ CC_OFFER_TIMER_DEFAULT

#define CC_OFFER_TIMER_DEFAULT   20 /* Seconds */

Definition at line 660 of file ccss.c.

◆ CC_RECALL_TIMER_DEFAULT

#define CC_RECALL_TIMER_DEFAULT   20 /* Seconds */

Definition at line 663 of file ccss.c.

◆ CC_RECALLING_DEVSTATE_DEFAULT

#define CC_RECALLING_DEVSTATE_DEFAULT   AST_DEVICE_RINGING

Definition at line 561 of file ccss.c.

◆ CCBS_AVAILABLE_TIMER_DEFAULT

#define CCBS_AVAILABLE_TIMER_DEFAULT   4800 /* Seconds */

Definition at line 662 of file ccss.c.

◆ CCNR_AVAILABLE_TIMER_DEFAULT

#define CCNR_AVAILABLE_TIMER_DEFAULT   7200 /* Seconds */

Definition at line 661 of file ccss.c.

◆ GLOBAL_CC_MAX_REQUESTS_DEFAULT

#define GLOBAL_CC_MAX_REQUESTS_DEFAULT   20

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

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

◆ match_flags

Enumerator
MATCH_NO_REQUEST 
MATCH_REQUEST 

Definition at line 475 of file ccss.c.

475 {
476 /* Only match agents that have not yet
477 * made a CC request
478 */
479 MATCH_NO_REQUEST = (1 << 0),
480 /* Only match agents that have made
481 * a CC request
482 */
483 MATCH_REQUEST = (1 << 1),
484};
@ MATCH_REQUEST
Definition: ccss.c:483
@ MATCH_NO_REQUEST
Definition: ccss.c:479

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

687{
688 struct ast_cc_config_params *params = __ast_malloc(sizeof(*params), file, line, function);
689
690 if (!params) {
691 return NULL;
692 }
693
695 return params;
696}
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:681
#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 4674 of file ccss.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4674 of file ccss.c.

◆ agent_destroy()

static void agent_destroy ( void *  data)
static

Definition at line 2528 of file ccss.c.

2529{
2530 struct ast_cc_agent *agent = data;
2531
2532 if (agent->callbacks) {
2533 agent->callbacks->destructor(agent);
2534 }
2536}
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:698
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 733 of file ccss.c.

734{
735 switch (policy) {
737 return "never";
739 return "native";
741 return "generic";
742 default:
743 /* This should never happen... */
744 return "";
745 }
746}
@ 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 3747 of file ccss.c.

3748{
3749 va_list ap;
3750 int res;
3751
3752 va_start(ap, debug);
3754 va_end(ap);
3755 return res;
3756}
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3301
static int debug
Global debug status.
Definition: res_xmpp.c:570

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

463{
464 struct cc_callback_helper helper = {.function = function, .args = args, .type = type};
465 struct cc_core_instance *core_instance;
466 if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper,
467 "Calling provided agent callback function"))) {
468 struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent");
469 cc_unref(core_instance, "agent callback done with the core_instance");
470 return agent;
471 }
472 return NULL;
473}
#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:155
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:149
static struct ao2_container * cc_core_instances
Definition: ccss.c:332
static int cc_agent_callback_helper(void *obj, void *args, int flags)
Definition: ccss.c:450
static const char type[]
Definition: chan_ooh323.c:109
ao2_callback_fn * function
Definition: ccss.c:445
struct ast_cc_agent * agent
Definition: ccss.c:346
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 3791 of file ccss.c.

3792{
3793 va_list ap;
3794 int res;
3795
3796 va_start(ap, debug);
3797 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3798 va_end(ap);
3799 return res;
3800}

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

3781{
3782 va_list ap;
3783 int res;
3784
3785 va_start(ap, debug);
3786 res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap);
3787 va_end(ap);
3788 return res;
3789}

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

3803{
3804 va_list ap;
3805 int res;
3806
3807 va_start(ap, debug);
3808 res = cc_request_state_change(CC_RECALLING, core_id, debug, ap);
3809 va_end(ap);
3810 return res;
3811}

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

1224{
1225 struct cc_agent_backend *backend = ast_calloc(1, sizeof(*backend));
1226
1227 if (!backend) {
1228 return -1;
1229 }
1230
1231 backend->callbacks = callbacks;
1235 return 0;
1236}
#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 @471 callbacks
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.c:1218
struct cc_agent_backend * next
Definition: ccss.c:1217

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

3603{
3604 struct ast_datastore *recall_datastore;
3605 struct cc_monitor_tree *interface_tree;
3606 struct ast_cc_monitor *monitor;
3607 struct cc_recall_ds_data *recall_data;
3608 struct ast_str *str = ast_str_create(64);
3609 int core_id;
3610
3611 if (!str) {
3612 return -1;
3613 }
3614
3615 ast_channel_lock(chan);
3616 if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3617 ast_channel_unlock(chan);
3618 ast_free(str);
3619 return -1;
3620 }
3621 recall_data = recall_datastore->data;
3622 interface_tree = recall_data->interface_tree;
3623 core_id = recall_data->core_id;
3624 ast_channel_unlock(chan);
3625
3626 AST_LIST_LOCK(interface_tree);
3627 monitor = AST_LIST_FIRST(interface_tree);
3629 AST_LIST_UNLOCK(interface_tree);
3630
3631 pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3632 ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3633 core_id, ast_str_buffer(str));
3634
3635 ast_free(str);
3636 return 0;
3637}
const char * str
Definition: app_jack.c:150
#define ast_free(a)
Definition: astmm.h:180
static const struct ast_datastore_info recall_ds_info
Definition: ccss.c:3372
static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str **str)
Definition: ccss.c:3559
static int cc_logger_level
Definition: ccss.c:139
#define ast_channel_lock(chan)
Definition: channel.h:2970
#define ast_channel_unlock(chan)
Definition: channel.h:2971
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:2428
#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:329
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3348

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

4065{
4067 struct cc_core_instance *core_instance;
4068 int res;
4069
4070 args = ast_calloc(1, sizeof(*args));
4071 if (!args) {
4072 return -1;
4073 }
4074
4075 core_instance = find_cc_core_instance(core_id);
4076 if (!core_instance) {
4077 ast_free(args);
4078 return -1;
4079 }
4080
4081 args->core_instance = core_instance;
4082 args->devstate = devstate;
4083
4085 if (res) {
4086 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4087 ast_free(args);
4088 }
4089 return res;
4090}
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:131
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:437
static int cc_status_response(void *data)
Definition: ccss.c:4043
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 1238 of file ccss.c.

1239{
1240 struct cc_agent_backend *backend;
1243 if (backend->callbacks == callbacks) {
1245 ast_free(backend);
1246 break;
1247 }
1248 }
1251}
#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 1493 of file ccss.c.

1494{
1495 struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data;
1496 int res;
1497 monitor->available_timer_id = -1;
1498 res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor");
1499 cc_unref(monitor, "Unref reference from scheduler\n");
1500 return res;
1501}
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:3912
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 4147 of file ccss.c.

4151{
4152 struct cc_control_payload *payload = ast_calloc(1, sizeof(*payload));
4153
4154 if (!payload) {
4155 return -1;
4156 }
4157 if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) {
4158 /* Something screwed up, we can't make a frame with this */
4159 ast_free(payload);
4160 return -1;
4161 }
4164 frame->data.ptr = payload;
4165 frame->datalen = sizeof(*payload);
4166 frame->mallocd = AST_MALLOCD_DATA;
4167 return 0;
4168}
enum ast_cc_service_type service
Definition: ccss.c:389
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:4092
#define AST_MALLOCD_DATA
@ AST_FRAME_CONTROL
@ AST_CONTROL_CC
union ast_frame::@228 data
struct ast_frame_subclass subclass
enum ast_frame_type frametype
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:227
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:245
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:298
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:310
void * private_data
Private data allocated by the callee.
Definition: ccss.c:262

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

4205{
4206 struct cc_control_payload payload;
4207 if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) {
4208 /* Something screwed up. Don't try to handle this payload */
4210 return;
4211 }
4212 ast_handle_cc_control_frame(inbound, NULL, &payload);
4213}
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:2299
static void call_destructor_with_no_monitor(const char *const monitor_type, void *private_data)
Definition: ccss.c:2198
@ 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 4170 of file ccss.c.

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

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

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

4216{
4217 const struct ast_channel_tech *chantech = ast_get_channel_tech(tech);
4218
4219 if (chantech && chantech->cc_callback) {
4220 chantech->cc_callback(inbound, dest, callback);
4221 }
4222
4223 return 0;
4224}
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:648
int(* cc_callback)(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
Call a function with cc parameters as a function parameter.
Definition: channel.h:847

References ast_get_channel_tech(), 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 3813 of file ccss.c.

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

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

699{
700 ast_free(params);
701}

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

861{
862 *dest = *src;
863}

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

682{
683 *params = cc_default_params;
684}
static const struct ast_cc_config_params cc_default_params
Definition: ccss.c:668

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

1990{
1991 struct ast_datastore *cc_datastore;
1992 struct dialed_cc_interfaces *cc_interfaces;
1993 struct ast_cc_monitor *monitor;
1994 struct extension_monitor_pvt *extension_pvt;
1995 struct extension_child_dialstring *child_dialstring;
1996 struct cc_monitor_tree *interface_tree;
1997 int id;
1998
1999 ast_channel_lock(incoming);
2000 if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) {
2001 ast_channel_unlock(incoming);
2002 return;
2003 }
2004
2005 cc_interfaces = cc_datastore->data;
2006 interface_tree = cc_interfaces->interface_tree;
2007 id = cc_interfaces->dial_parent_id;
2008 ast_channel_unlock(incoming);
2009
2010 AST_LIST_LOCK(interface_tree);
2011 AST_LIST_TRAVERSE(interface_tree, monitor, next) {
2012 if (monitor->id == id) {
2013 break;
2014 }
2015 }
2016
2017 if (!monitor) {
2018 AST_LIST_UNLOCK(interface_tree);
2019 return;
2020 }
2021
2022 extension_pvt = monitor->private_data;
2023 if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) {
2024 AST_LIST_UNLOCK(interface_tree);
2025 return;
2026 }
2027 ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring));
2028 ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name));
2029 child_dialstring->is_valid = 1;
2030 AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next);
2031 AST_LIST_UNLOCK(interface_tree);
2032}
enum queue_result id
Definition: app_queue.c:1808
#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:1913
unsigned int dial_parent_id
Definition: ccss.c:1886
Data regarding an extension monitor's child's dialstrings.
Definition: ccss.c:1744
char device_name[AST_CHANNEL_NAME]
The name of the device being dialed.
Definition: ccss.c:1779
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition: ccss.c:1794
char original_dialstring[AST_CHANNEL_NAME]
the original dialstring used to call a particular device
Definition: ccss.c:1760
Private data for an extension monitor.
Definition: ccss.c:1801
struct extension_monitor_pvt::@328 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 3850 of file ccss.c.

3851{
3852 va_list ap;
3853 int res;
3854
3855 va_start(ap, debug);
3856 res = cc_request_state_change(CC_FAILED, core_id, debug, ap);
3857 va_end(ap);
3858 return res;
3859}

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

2472{
2473 struct ast_datastore *datastore;
2474 struct dialed_cc_interfaces *cc_interfaces;
2475 int core_id_return;
2476
2477 ast_channel_lock(chan);
2478 if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2479 ast_channel_unlock(chan);
2480 return -1;
2481 }
2482
2483 cc_interfaces = datastore->data;
2484 core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id;
2485 ast_channel_unlock(chan);
2486 return core_id_return;
2487
2488}

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

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

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

766{
767 const char *value = NULL;
768
769 if (!strcasecmp(name, "cc_callback_sub")) {
771 } else if (!strcasecmp(name, "cc_agent_policy")) {
773 } else if (!strcasecmp(name, "cc_monitor_policy")) {
775 } else if (!strcasecmp(name, "cc_agent_dialstring")) {
777 }
778 if (value) {
779 ast_copy_string(buf, value, buf_len);
780 return 0;
781 }
782
783 /* The rest of these are all ints of some sort and require some
784 * snprintf-itude
785 */
786
787 if (!strcasecmp(name, "cc_offer_timer")) {
788 snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params));
789 } else if (!strcasecmp(name, "ccnr_available_timer")) {
790 snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params));
791 } else if (!strcasecmp(name, "ccbs_available_timer")) {
792 snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params));
793 } else if (!strcasecmp(name, "cc_max_agents")) {
794 snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params));
795 } else if (!strcasecmp(name, "cc_max_monitors")) {
796 snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params));
797 } else if (!strcasecmp(name, "cc_recall_timer")) {
798 snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params));
799 } else {
800 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
801 return -1;
802 }
803
804 return 0;
805}
#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:929
static const char * agent_policy_to_str(enum ast_cc_agent_policies policy)
Definition: ccss.c:733
unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
Get the cc_offer_timer.
Definition: ccss.c:899
unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
Get the ccbs_available_timer.
Definition: ccss.c:944
unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
Get the ccnr_available_timer.
Definition: ccss.c:914
unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
Get the cc_max_agents.
Definition: ccss.c:973
const char * ast_get_cc_callback_sub(struct ast_cc_config_params *config)
Get the name of the callback subroutine.
Definition: ccss.c:993
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition: ccss.c:983
static const char * monitor_policy_to_str(enum ast_cc_monitor_policies policy)
Definition: ccss.c:748
const char * ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
Get the cc_agent_dialstring.
Definition: ccss.c:959
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 846 of file ccss.c.

847{
848 return (!strcasecmp(name, "cc_agent_policy") ||
849 !strcasecmp(name, "cc_monitor_policy") ||
850 !strcasecmp(name, "cc_offer_timer") ||
851 !strcasecmp(name, "ccnr_available_timer") ||
852 !strcasecmp(name, "ccbs_available_timer") ||
853 !strcasecmp(name, "cc_max_agents") ||
854 !strcasecmp(name, "cc_max_monitors") ||
855 !strcasecmp(name, "cc_callback_sub") ||
856 !strcasecmp(name, "cc_agent_dialstring") ||
857 !strcasecmp(name, "cc_recall_timer"));
858}

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

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

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

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

4340{
4341 struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,};
4342
4343 ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents");
4344 ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count);
4345 return data.count;
4346}
@ OBJ_NODATA
Definition: astobj2.h:1044
static int count_monitors_cb(void *obj, void *arg, int flags)
Definition: ccss.c:4319
const char * device_name
Definition: ccss.c:4314

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

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

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

4023{
4024 int res;
4025 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4026
4027 if (!core_instance) {
4028 return -1;
4029 }
4030
4032 if (res) {
4033 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4034 }
4035 return res;
4036}
static int cc_party_b_free(void *data)
Definition: ccss.c:4010

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

1169{
1170 struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend));
1171
1172 if (!backend) {
1173 return -1;
1174 }
1175
1176 backend->callbacks = callbacks;
1177
1181 return 0;
1182}
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.c:1163
struct cc_monitor_backend * next
Definition: ccss.c:1162

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

3759{
3760 va_list ap;
3761 int res;
3762
3763 va_start(ap, debug);
3764 res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3765 va_end(ap);
3766 return res;
3767}

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

3958{
3959 int res;
3960 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3961
3962 if (!core_instance) {
3963 return -1;
3964 }
3965
3967 if (res) {
3968 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3969 }
3970 return res;
3971}
static int cc_status_request(void *data)
Definition: ccss.c:3947

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

3995{
3996 int res;
3997 struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3998
3999 if (!core_instance) {
4000 return -1;
4001 }
4002
4004 if (res) {
4005 cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4006 }
4007 return res;
4008}
static int cc_stop_ringing(void *data)
Definition: ccss.c:3973

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

1202{
1203 struct cc_monitor_backend *backend;
1206 if (backend->callbacks == callbacks) {
1208 ast_free(backend);
1209 break;
1210 }
1211 }
1214}

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

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

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

2467{
2469}
static unsigned int global_cc_max_requests
Definition: ccss.c:143
static int cc_request_count
Definition: ccss.c:147

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

809{
810 unsigned int value_as_uint;
811 if (!strcasecmp(name, "cc_agent_policy")) {
813 } else if (!strcasecmp(name, "cc_monitor_policy")) {
815 } else if (!strcasecmp(name, "cc_agent_dialstring")) {
817 } else if (!strcasecmp(name, "cc_callback_sub")) {
819 return 0;
820 }
821
822 if (sscanf(value, "%30u", &value_as_uint) != 1) {
823 return -1;
824 }
825
826 if (!strcasecmp(name, "cc_offer_timer")) {
827 ast_set_cc_offer_timer(params, value_as_uint);
828 } else if (!strcasecmp(name, "ccnr_available_timer")) {
829 ast_set_ccnr_available_timer(params, value_as_uint);
830 } else if (!strcasecmp(name, "ccbs_available_timer")) {
831 ast_set_ccbs_available_timer(params, value_as_uint);
832 } else if (!strcasecmp(name, "cc_max_agents")) {
833 ast_set_cc_max_agents(params, value_as_uint);
834 } else if (!strcasecmp(name, "cc_max_monitors")) {
835 ast_set_cc_max_monitors(params, value_as_uint);
836 } else if (!strcasecmp(name, "cc_recall_timer")) {
837 ast_set_cc_recall_timer(params, value_as_uint);
838 } else {
839 ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
840 return -1;
841 }
842
843 return 0;
844}
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:870
void ast_set_cc_max_monitors(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_monitors.
Definition: ccss.c:988
void ast_set_ccbs_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccbs_available_timer.
Definition: ccss.c:949
void ast_set_cc_callback_sub(struct ast_cc_config_params *config, const char *const value)
Set the callback subroutine name.
Definition: ccss.c:998
void ast_set_cc_agent_dialstring(struct ast_cc_config_params *config, const char *const value)
Set the cc_agent_dialstring.
Definition: ccss.c:964
void ast_set_cc_offer_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_offer_timer.
Definition: ccss.c:904
void ast_set_cc_max_agents(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_agents.
Definition: ccss.c:978
static enum ast_cc_monitor_policies str_to_monitor_policy(const char *const value)
Definition: ccss.c:717
void ast_set_ccnr_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccnr_available_timer.
Definition: ccss.c:919
static enum ast_cc_agent_policies str_to_agent_policy(const char *const value)
Definition: ccss.c:703
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:887
void ast_set_cc_recall_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_recall_timer.
Definition: ccss.c:934

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

960{
961 return config->cc_agent_dialstring;
962}
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 865 of file ccss.c.

866{
867 return config->cc_agent_policy;
868}

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

994{
995 return config->cc_callback_sub;
996}

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

974{
975 return config->cc_max_agents;
976}

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

984{
985 return config->cc_max_monitors;
986}

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

883{
884 return config->cc_monitor_policy;
885}

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

900{
901 return config->cc_offer_timer;
902}

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

930{
931 return config->cc_recall_timer;
932}

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

945{
946 return config->ccbs_available_timer;
947}

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

915{
916 return config->ccnr_available_timer;
917}

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

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

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

3692{
3693 struct ast_datastore *cc_datastore;
3694 struct ast_datastore *cc_recall_datastore;
3695 struct dialed_cc_interfaces *cc_interfaces;
3696 struct cc_recall_ds_data *recall_cc_data;
3697
3698 ast_channel_lock(chan);
3699 if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
3700 cc_interfaces = cc_datastore->data;
3701 cc_interfaces->ignore = 1;
3702 }
3703
3704 if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3705 recall_cc_data = cc_recall_datastore->data;
3706 recall_cc_data->ignore = 1;
3707 }
3708 ast_channel_unlock(chan);
3709}

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

4122{
4123 struct ast_frame frame = {0,};
4124 char device_name[AST_CHANNEL_NAME];
4125 int retval;
4126 struct ast_cc_config_params *cc_params;
4127
4128 cc_params = ast_channel_get_cc_config_params(chan);
4129 if (!cc_params) {
4130 return -1;
4131 }
4132 ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4133 if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
4134 ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
4135 return -1;
4136 }
4137
4138 if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) {
4139 /* Frame building failed. We can't use this. */
4140 return -1;
4141 }
4142 retval = ast_queue_frame(chan, &frame);
4143 ast_frfree(&frame);
4144 return retval;
4145}
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:4339
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:4147
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:1158
#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, 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 964 of file ccss.c.

965{
966 if (ast_strlen_zero(value)) {
967 config->cc_agent_dialstring[0] = '\0';
968 } else {
969 ast_copy_string(config->cc_agent_dialstring, value, sizeof(config->cc_agent_dialstring));
970 }
971}

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

871{
872 /* Screw C and its weak type checking for making me have to do this
873 * validation at runtime.
874 */
875 if (value < AST_CC_AGENT_NEVER || value > AST_CC_AGENT_GENERIC) {
876 return -1;
877 }
878 config->cc_agent_policy = value;
879 return 0;
880}

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

999{
1000 if (ast_strlen_zero(value)) {
1001 config->cc_callback_sub[0] = '\0';
1002 } else {
1003 ast_copy_string(config->cc_callback_sub, value, sizeof(config->cc_callback_sub));
1004 }
1005}

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

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

979{
980 config->cc_max_agents = value;
981}

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

989{
990 config->cc_max_monitors = value;
991}

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

888{
889 /* Screw C and its weak type checking for making me have to do this
890 * validation at runtime.
891 */
892 if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) {
893 return -1;
894 }
895 config->cc_monitor_policy = value;
896 return 0;
897}
@ 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 904 of file ccss.c.

905{
906 /* 0 is an unreasonable value for any timer. Stick with the default */
907 if (value == 0) {
908 ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer);
909 return;
910 }
911 config->cc_offer_timer = value;
912}

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

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

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

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

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

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

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

3379{
3380 struct ast_datastore *recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL);
3381 struct cc_recall_ds_data *recall_data;
3382 struct cc_core_instance *core_instance;
3383
3384 if (!recall_datastore) {
3385 return -1;
3386 }
3387
3388 if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) {
3389 ast_datastore_free(recall_datastore);
3390 return -1;
3391 }
3392
3393 if (!(core_instance = find_cc_core_instance(core_id))) {
3394 ast_free(recall_data);
3395 ast_datastore_free(recall_datastore);
3396 return -1;
3397 }
3398
3399 recall_data->interface_tree = cc_ref(core_instance->monitors,
3400 "Bump refcount for monitor tree for recall datastore");
3401 recall_data->core_id = core_id;
3402 recall_datastore->data = recall_data;
3403 recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
3404 ast_channel_lock(chan);
3405 ast_channel_datastore_add(chan, recall_datastore);
3406 ast_channel_unlock(chan);
3407 cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref");
3408 return 0;
3409}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2414
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:194
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
unsigned int inheritance
Definition: datastore.h:69

References ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_free, cc_ref(), cc_unref(), cc_core_instance::core_id, cc_recall_ds_data::core_id, ast_datastore::data, DATASTORE_INHERIT_FOREVER, find_cc_core_instance(), ast_datastore::inheritance, cc_recall_ds_data::interface_tree, cc_core_instance::monitors, NULL, 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 3559 of file ccss.c.

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

2199{
2200 const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type);
2201
2202 if (!monitor_callbacks) {
2203 return;
2204 }
2205
2206 monitor_callbacks->destructor(private_data);
2207}
static const struct ast_cc_monitor_callbacks * find_monitor_callbacks(const char *const type)
Definition: ccss.c:1184
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 3199 of file ccss.c.

3200{
3201 struct ast_cc_monitor *monitor_iter;
3202 AST_LIST_LOCK(core_instance->monitors);
3203 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3204 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3205 if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) {
3207 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3208 monitor_iter->interface->device_name, 1);
3209 cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor");
3210 }
3211 }
3212 }
3214
3215 if (!has_device_monitors(core_instance)) {
3216 ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers");
3217 }
3218 AST_LIST_UNLOCK(core_instance->monitors);
3219}
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:3066
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3850
@ 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 3141 of file ccss.c.

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

451{
452 struct cc_core_instance *core_instance = obj;
453 struct cc_callback_helper *helper = args;
454
455 if (strcmp(core_instance->agent->callbacks->type, helper->type)) {
456 return 0;
457 }
458
459 return helper->function(core_instance->agent, helper->args, flags);
460}
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:857
const char * type
Definition: ccss.c:447
void * args
Definition: ccss.c:446

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

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

3031{
3032 /* This should never happen... */
3033 ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n");
3034 return -1;
3035}

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

4095{
4096 struct ast_datastore *datastore;
4097 struct dialed_cc_interfaces *cc_interfaces;
4098 int dial_parent_id;
4099
4100 ast_channel_lock(chan);
4102 if (!datastore) {
4103 ast_channel_unlock(chan);
4104 return -1;
4105 }
4106 cc_interfaces = datastore->data;
4107 dial_parent_id = cc_interfaces->dial_parent_id;
4108 ast_channel_unlock(chan);
4109
4110 payload->monitor_type = monitor_type;
4111 payload->private_data = private_data;
4112 payload->service = service;
4113 ast_cc_copy_config_params(&payload->config_params, cc_params);
4115 ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
4116 ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring));
4117 return 0;
4118}
int parent_interface_id
ID of parent extension.
Definition: ccss.c:289
struct ast_cc_config_params config_params
Configuration parameters used by this endpoint.
Definition: ccss.c:280

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

3161{
3162 core_instance->agent->callbacks->callee_available(core_instance->agent);
3163 return 0;
3164}
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 3188 of file ccss.c.

3189{
3190 /* Callee was available, but caller was busy, call agent's begin_monitoring callback
3191 * and call monitor's suspend callback.
3192 */
3193 suspend(core_instance);
3194 core_instance->agent->callbacks->start_monitoring(core_instance->agent);
3195 cc_publish_callerstartmonitoring(core_instance->core_id, core_instance->agent->device_name);
3196 return 0;
3197}
static void cc_publish_callerstartmonitoring(int core_id, const char *caller)
Definition: ccss.c:1105
static void suspend(struct cc_core_instance *core_instance)
Definition: ccss.c:3166
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 3037 of file ccss.c.

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

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

3106{
3108 ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n");
3109 core_instance->agent->callbacks->respond(core_instance->agent,
3111 ast_cc_failed(core_instance->core_id, "Too many requests in the system");
3112 return -1;
3113 }
3114 core_instance->agent->callbacks->stop_offer_timer(core_instance->agent);
3115 request_cc(core_instance);
3116 return 0;
3117}
static void request_cc(struct cc_core_instance *core_instance)
Definition: ccss.c:3081
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:2466
@ 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 4465 of file ccss.c.

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

4433{
4434 struct ast_cc_monitor *child_monitor_iter = monitor;
4435 if (!monitor) {
4436 return;
4437 }
4438
4439 ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name);
4441 ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered));
4442 }
4443 ast_cli(fd, "\n");
4444
4445 while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) {
4446 if (child_monitor_iter->parent_id == monitor->id) {
4447 cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id);
4448 }
4449 }
4450}
static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
Definition: ccss.c:4432
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 3230 of file ccss.c.

3231{
3232 /* Recall has made progress, call agent and monitor destructor functions
3233 */
3234 cc_publish_recallcomplete(core_instance->core_id, core_instance->agent->device_name);
3235 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed");
3236 return 0;
3237}
#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:1127

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

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

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

430{
431 struct cc_core_instance *core_instance1 = obj;
432 struct cc_core_instance *core_instance2 = arg;
433
434 return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0;
435}
@ 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 2901 of file ccss.c.

2902{
2903 struct cc_core_instance *core_instance = data;
2904 ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id);
2905 if (core_instance->agent) {
2906 cc_unref(core_instance->agent, "Core instance is done with the agent now");
2907 }
2908 if (core_instance->monitors) {
2909 core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list");
2910 }
2911}

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

424{
425 const struct cc_core_instance *core_instance = obj;
426 return core_instance->core_id;
427}

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

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

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

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

2035{
2036 struct ast_cc_monitor *monitor_iter;
2037 struct extension_monitor_pvt *extension_pvt;
2038 struct extension_child_dialstring *child_dialstring;
2039
2040 AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
2041 if (monitor_iter->id == parent_id) {
2042 break;
2043 }
2044 }
2045
2046 if (!monitor_iter) {
2047 return;
2048 }
2049 extension_pvt = monitor_iter->private_data;
2050
2051 AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
2052 if (!strcmp(child_dialstring->device_name, device_name)) {
2053 child_dialstring->is_valid = is_valid;
2054 break;
2055 }
2056 }
2057}
struct extension_child_dialstring * next
Definition: ccss.c:1795

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

1806{
1807 struct extension_monitor_pvt *extension_pvt = private_data;
1808 struct extension_child_dialstring *child_dialstring;
1809
1810 /* This shouldn't be possible, but I'm paranoid */
1811 if (!extension_pvt) {
1812 return;
1813 }
1814
1815 while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) {
1816 ast_free(child_dialstring);
1817 }
1818 ast_free(extension_pvt);
1819}
#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 2073 of file ccss.c.

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

3240{
3241 cc_publish_failure(core_instance->core_id, core_instance->agent->device_name, args->debug);
3242 ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed");
3243 return 0;
3244}
static void cc_publish_failure(int core_id, const char *caller, const char *reason)
Definition: ccss.c:1138

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

2885{
2887
2888 if (!agent_pvt) {
2889 /* The agent constructor probably failed. */
2890 return;
2891 }
2892
2894 if (agent_pvt->sub) {
2896 }
2897
2899}
static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
Definition: ccss.c:2706
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:998
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 2653 of file ccss.c.

2654{
2655 struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
2656
2657 if (!generic_pvt) {
2658 return -1;
2659 }
2660
2661 generic_pvt->offer_timer_id = -1;
2662 if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
2663 ast_copy_string(generic_pvt->cid_num, ast_channel_caller(chan)->id.number.str, sizeof(generic_pvt->cid_num));
2664 }
2665 if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
2666 ast_copy_string(generic_pvt->cid_name, ast_channel_caller(chan)->id.name.str, sizeof(generic_pvt->cid_name));
2667 }
2668 ast_copy_string(generic_pvt->exten, ast_channel_exten(chan), sizeof(generic_pvt->exten));
2669 ast_copy_string(generic_pvt->context, ast_channel_context(chan), sizeof(generic_pvt->context));
2670 agent->private_data = generic_pvt;
2672 return 0;
2673}
@ 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:2650
char cid_num[AST_CHANNEL_NAME]
Definition: ccss.c:2626
char cid_name[AST_CHANNEL_NAME]
Definition: ccss.c:2634
char exten[AST_CHANNEL_NAME]
Definition: ccss.c:2642
Number structure.
Definition: app_followme.c:157
#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 2868 of file ccss.c.

2869{
2870 pthread_t clotho;
2871 enum ast_device_state current_state = ast_device_state(agent->device_name);
2872
2873 if (!cc_generic_is_device_available(current_state)) {
2874 /* We can't try to contact the device right now because he's not available
2875 * Let the core know he's busy.
2876 */
2877 ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name);
2878 return 0;
2879 }
2881 return 0;
2882}
int ast_cc_agent_caller_busy(int core_id, const char *debug,...)
Indicate that the caller is busy.
Definition: ccss.c:3780
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1297
static void * generic_recall(void *data)
Definition: ccss.c:2800
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 2719 of file ccss.c.

2720{
2721 /* The generic agent doesn't have to do anything special to
2722 * acknowledge a CC request. Just return.
2723 */
2724 return;
2725}

◆ cc_generic_agent_start_monitoring()

static int cc_generic_agent_start_monitoring ( struct ast_cc_agent agent)
static

Definition at line 2775 of file ccss.c.

2776{
2777 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2778 struct ast_str *str = ast_str_alloca(128);
2779 struct stasis_topic *device_specific_topic;
2780
2781 ast_assert(generic_pvt->sub == NULL);
2782 ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n",
2783 agent->device_name);
2784
2785 device_specific_topic = ast_device_state_topic(agent->device_name);
2786 if (!device_specific_topic) {
2787 return -1;
2788 }
2789
2790 if (!(generic_pvt->sub = stasis_subscribe(device_specific_topic, generic_agent_devstate_cb, agent))) {
2791 return -1;
2792 }
2796 cc_ref(agent, "Ref agent for subscription");
2797 return 0;
2798}
static void generic_agent_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: ccss.c:2745
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:686
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:1050
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:1104
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:649
struct stasis_subscription * sub
Definition: ccss.c:2612

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

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

2728{
2730 return 0;
2731}
int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate)
Response with a caller's current status.
Definition: ccss.c:4064

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

2707{
2708 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2709
2710 if (generic_pvt->offer_timer_id != -1) {
2711 if (!ast_sched_del(cc_sched_context, generic_pvt->offer_timer_id)) {
2712 cc_unref(agent, "Remove scheduler's reference to the agent");
2713 }
2714 generic_pvt->offer_timer_id = -1;
2715 }
2716 return 0;
2717}
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 2733 of file ccss.c.

2734{
2735 struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name));
2736
2737 if (!recall_chan) {
2738 return 0;
2739 }
2740
2742 return 0;
2743}
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:1461
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2500
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1168
Main Channel structure associated with a channel.

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

◆ cc_generic_is_device_available()

static int cc_generic_is_device_available ( enum ast_device_state  state)
static

◆ cc_generic_monitor_cancel_available_timer()

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

Definition at line 1635 of file ccss.c.

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

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

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

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

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

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

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

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

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

1722{
1723 struct ast_cc_interface *interface = data;
1724 ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name);
1725 ast_cc_config_params_destroy(interface->config_params);
1726}

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

1843{
1844 struct cc_monitor_tree *cc_interface_tree = data;
1845 struct ast_cc_monitor *monitor;
1846 while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
1847 if (monitor->callbacks) {
1848 monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id);
1849 }
1850 cc_unref(monitor, "Destroying all monitors");
1851 }
1852 AST_LIST_HEAD_DESTROY(cc_interface_tree);
1853}
#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 2122 of file ccss.c.

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

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

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

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

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

3712{
3713 va_list ap;
3714 int res;
3715
3716 va_start(ap, debug);
3717 res = cc_request_state_change(CC_CALLER_OFFERED, core_id, debug, ap);
3718 va_end(ap);
3719 return res;
3720}

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

4011{
4012 struct cc_core_instance *core_instance = data;
4013 int res = 0;
4014
4015 if (core_instance->agent->callbacks->party_b_free) {
4016 res = core_instance->agent->callbacks->party_b_free(core_instance->agent);
4017 }
4018 cc_unref(core_instance, "Party B free finished. Unref core_instance");
4019 return res;
4020}
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 1007 of file ccss.c.

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

1048{
1049 struct ast_json *extras;
1050
1051 extras = ast_json_pack("{s: s, s: s}",
1052 "callee", callee,
1053 "service", service);
1054
1055 cc_publish(ast_cc_available_type(), core_id, extras);
1056 ast_json_unref(extras);
1057}
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1007
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 1116 of file ccss.c.

1117{
1118 struct ast_json *extras;
1119
1120 extras = ast_json_pack("{s: s}",
1121 "caller", caller);
1122
1123 cc_publish(ast_cc_callerrecalling_type(), core_id, extras);
1124 ast_json_unref(extras);
1125}
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 1105 of file ccss.c.

1106{
1107 struct ast_json *extras;
1108
1109 extras = ast_json_pack("{s: s}",
1110 "caller", caller);
1111
1113 ast_json_unref(extras);
1114}
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 1094 of file ccss.c.

1095{
1096 struct ast_json *extras;
1097
1098 extras = ast_json_pack("{s: s}",
1099 "caller", caller);
1100
1101 cc_publish(ast_cc_callerstopmonitoring_type(), core_id, extras);
1102 ast_json_unref(extras);
1103}
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 1138 of file ccss.c.

1139{
1140 struct ast_json *extras;
1141
1142 extras = ast_json_pack("{s: s, s: s}",
1143 "caller", caller,
1144 "reason", reason);
1145
1146 cc_publish(ast_cc_failure_type(), core_id, extras);
1147 ast_json_unref(extras);
1148}
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 1150 of file ccss.c.

1151{
1152 struct ast_json *extras;
1153
1154 extras = ast_json_pack("{s: s}",
1155 "callee", callee);
1156
1157 cc_publish(ast_cc_monitorfailed_type(), core_id, extras);
1158 ast_json_unref(extras);
1159}
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 1059 of file ccss.c.

1060{
1061 struct ast_json *extras;
1062
1063 extras = ast_json_pack("{s: s, s: I}",
1064 "caller", caller,
1065 "expires", (ast_json_int_t)expires);
1066
1067 cc_publish(ast_cc_offertimerstart_type(), core_id, extras);
1068 ast_json_unref(extras);
1069}
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 1127 of file ccss.c.

1128{
1129 struct ast_json *extras;
1130
1131 extras = ast_json_pack("{s: s}",
1132 "caller", caller);
1133
1134 cc_publish(ast_cc_recallcomplete_type(), core_id, extras);
1135 ast_json_unref(extras);
1136}
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 1083 of file ccss.c.

1084{
1085 struct ast_json *extras;
1086
1087 extras = ast_json_pack("{s: s}",
1088 "caller", caller);
1089
1090 cc_publish(ast_cc_requestacknowledged_type(), core_id, extras);
1091 ast_json_unref(extras);
1092}
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 1071 of file ccss.c.

1072{
1073 struct ast_json *extras;
1074
1075 extras = ast_json_pack("{s: s, s: s}",
1076 "caller", caller,
1077 "callee", callee);
1078
1079 cc_publish(ast_cc_requested_type(), core_id, extras);
1080 ast_json_unref(extras);
1081}
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 3365 of file ccss.c.

3366{
3367 struct cc_recall_ds_data *recall_data = data;
3368 recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree");
3369 ast_free(recall_data);
3370}

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

3352{
3353 struct cc_recall_ds_data *old_data = data;
3354 struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data));
3355
3356 if (!new_data) {
3357 return NULL;
3358 }
3359 new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate");
3360 new_data->core_id = old_data->core_id;
3361 new_data->nested = 1;
3362 return new_data;
3363}

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

3222{
3223 /* Both caller and callee are available, call agent's recall callback
3224 */
3225 cancel_available_timer(core_instance);
3226 cc_publish_callerrecalling(core_instance->core_id, core_instance->agent->device_name);
3227 return 0;
3228}
static void cancel_available_timer(struct cc_core_instance *core_instance)
Definition: ccss.c:3199
static void cc_publish_callerrecalling(int core_id, const char *caller)
Definition: ccss.c:1116

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

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

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

419{
420 return cc_service_to_string_map[service].service_string;
421}
static const struct @321 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 590 of file ccss.c.

591{
593}
static enum ast_device_state cc_state_to_devstate_map[]
Definition: ccss.c:569

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

414{
415 return cc_state_to_string_map[state].state_string;
416}
static const struct @322 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 3947 of file ccss.c.

3948{
3949 struct cc_core_instance *core_instance= data;
3950 int res;
3951
3952 res = core_instance->agent->callbacks->status_request(core_instance->agent);
3953 cc_unref(core_instance, "Status request finished. Unref core instance");
3954 return res;
3955}
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 4043 of file ccss.c.

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

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

3531{
3532 char dialstring_search[AST_CHANNEL_NAME + 1];
3533
3534 if (ast_strlen_zero(dialstring)) {
3535 /* No dialstring to append. */
3536 return;
3537 }
3538 snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&');
3539 if (strstr(ast_str_buffer(*str), dialstring_search)) {
3540 return;
3541 }
3542 ast_str_append(str, 0, "%s", dialstring_search);
3543}
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 4279 of file ccss.c.

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

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

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

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

607{
608 struct cc_core_instance *core_instance;
609 unsigned long match_flags;
610 enum ast_device_state cc_current_state;
611
614 (char *) device_name, &match_flags,
615 "Find Core Instance for ccss_device_state request.");
616 if (!core_instance) {
618 "Couldn't find a core instance for caller %s\n", device_name);
620 }
621
623 "Core %d: Found core_instance for caller %s in state %s\n",
624 core_instance->core_id, device_name, cc_state_to_string(core_instance->current_state));
625
626 if (strcmp(core_instance->agent->callbacks->type, "generic")) {
628 "Core %d: Device State is only for generic agent types.\n",
629 core_instance->core_id);
630 cc_unref(core_instance, "Unref core_instance since ccss_device_state was called with native agent");
632 }
633 cc_current_state = cc_state_to_devstate(core_instance->current_state);
634 cc_unref(core_instance, "Unref core_instance done with ccss_device_state");
635 return cc_current_state;
636}
static enum ast_device_state cc_state_to_devstate(enum cc_state state)
Definition: ccss.c:590

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

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

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

2517{
2518 ast_assert(callbacks->init != NULL);
2519 ast_assert(callbacks->start_offer_timer != NULL);
2520 ast_assert(callbacks->stop_offer_timer != NULL);
2521 ast_assert(callbacks->respond != NULL);
2522 ast_assert(callbacks->status_request != NULL);
2523 ast_assert(callbacks->start_monitoring != NULL);
2524 ast_assert(callbacks->callee_available != NULL);
2525 ast_assert(callbacks->destructor != NULL);
2526}

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

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

2491{
2493
2494 ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents");
2495 ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count);
2496 return data.count;
2497}
static int count_agents_cb(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:536
int core_id_exception
Definition: ccss.c:525

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

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

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

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

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

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

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

1929{
1930 struct dialed_cc_interfaces *cc_interfaces = data;
1931 cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree");
1932 ast_free(cc_interfaces);
1933}

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

1949{
1950 struct dialed_cc_interfaces *old_cc_interfaces = data;
1951 struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces));
1952 if (!new_cc_interfaces) {
1953 return NULL;
1954 }
1955 new_cc_interfaces->ignore = old_cc_interfaces->ignore;
1956 new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id;
1957 new_cc_interfaces->is_original_caller = 0;
1958 cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree");
1959 new_cc_interfaces->core_id = old_cc_interfaces->core_id;
1960 new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree;
1961 return new_cc_interfaces;
1962}

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

1980{
1981 struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt));
1982 if (!ext_pvt) {
1983 return NULL;
1984 }
1986 return ext_pvt;
1987}
#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 1253 of file ccss.c.

1254{
1255 struct cc_agent_backend *backend;
1256 const struct ast_cc_agent_callbacks *callbacks = NULL;
1257 struct ast_cc_config_params *cc_params;
1258 char type[32];
1259
1260 cc_params = ast_channel_get_cc_config_params(chan);
1261 if (!cc_params) {
1262 return NULL;
1263 }
1264 switch (ast_get_cc_agent_policy(cc_params)) {
1266 ast_copy_string(type, "generic", sizeof(type));
1267 break;
1269 ast_channel_get_cc_agent_type(chan, type, sizeof(type));
1270 break;
1271 default:
1272 ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n");
1273 return NULL;
1274 }
1275
1277 AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) {
1278 if (!strcmp(backend->callbacks->type, type)) {
1279 ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type);
1280 callbacks = backend->callbacks;
1281 break;
1282 }
1283 }
1285 return callbacks;
1286}
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:10539
#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 1370 of file ccss.c.

1371{
1372 struct generic_monitor_instance_list finder = {0};
1373 char *uppertech = ast_strdupa(device_name);
1374 ast_tech_to_upper(uppertech);
1375 finder.device_name = uppertech;
1376
1377 return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list");
1378}
#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 1184 of file ccss.c.

1185{
1186 struct cc_monitor_backend *backend;
1187 const struct ast_cc_monitor_callbacks *callbacks = NULL;
1188
1190 AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) {
1191 if (!strcmp(backend->callbacks->type, type)) {
1192 ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type);
1193 callbacks = backend->callbacks;
1194 break;
1195 }
1196 }
1198 return callbacks;
1199}
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 2745 of file ccss.c.

2746{
2747 struct ast_cc_agent *agent = userdata;
2748 enum ast_device_state new_state;
2749 struct ast_device_state_message *dev_state;
2750 struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2751
2753 cc_unref(agent, "Done holding ref for subscription");
2754 return;
2756 return;
2757 }
2758
2759 dev_state = stasis_message_data(msg);
2760 if (dev_state->eid) {
2761 /* ignore non-aggregate states */
2762 return;
2763 }
2764
2765 new_state = dev_state->state;
2766 if (!cc_generic_is_device_available(new_state)) {
2767 /* Not interested in this new state of the device. It is still busy. */
2768 return;
2769 }
2770
2771 generic_pvt->sub = stasis_unsubscribe(sub);
2772 ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name);
2773}
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:3791
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:1201
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 1468 of file ccss.c.

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

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

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

1381{
1382 struct generic_monitor_instance_list *generic_list = obj;
1383 struct generic_monitor_instance *generic_instance;
1384
1385 generic_list->sub = stasis_unsubscribe(generic_list->sub);
1386 while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) {
1387 ast_free(generic_instance);
1388 }
1389 ast_free((char *)generic_list->device_name);
1390}

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

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

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

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

3067{
3068 struct ast_cc_monitor *iter;
3069 int res = 0;
3070
3071 AST_LIST_TRAVERSE(core_instance->monitors, iter, next) {
3073 res = 1;
3074 break;
3075 }
3076 }
3077
3078 return res;
3079}

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

4408{
4409 struct ast_config *cc_config;
4410 struct ast_flags config_flags = { 0, };
4411
4412 cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
4413 if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
4415 "Could not find valid ccss.conf file. Using cc_[state]_devstate defaults\n");
4416 return;
4417 }
4418
4419 initialize_cc_devstate_map_helper(cc_config, CC_AVAILABLE, "cc_available_devstate");
4420 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_OFFERED, "cc_caller_offered_devstate");
4421 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_REQUESTED, "cc_caller_requested_devstate");
4422 initialize_cc_devstate_map_helper(cc_config, CC_ACTIVE, "cc_active_devstate");
4423 initialize_cc_devstate_map_helper(cc_config, CC_CALLEE_READY, "cc_callee_ready_devstate");
4424 initialize_cc_devstate_map_helper(cc_config, CC_CALLER_BUSY, "cc_caller_busy_devstate");
4425 initialize_cc_devstate_map_helper(cc_config, CC_RECALLING, "cc_recalling_devstate");
4426 initialize_cc_devstate_map_helper(cc_config, CC_COMPLETE, "cc_complete_devstate");
4427 initialize_cc_devstate_map_helper(cc_config, CC_FAILED, "cc_failed_devstate");
4428
4429 ast_config_destroy(cc_config);
4430}
static void initialize_cc_devstate_map_helper(struct ast_config *cc_config, enum cc_state state, const char *cc_setting)
Definition: ccss.c:4383
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:3541
#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 4383 of file ccss.c.

4384{
4385 const char *cc_devstate_str;
4386 enum ast_device_state this_devstate;
4387
4388 if ((cc_devstate_str = ast_variable_retrieve(cc_config, "general", cc_setting))) {
4389 this_devstate = ast_devstate_val(cc_devstate_str);
4390 if (this_devstate != AST_DEVICE_UNKNOWN) {
4391 cc_state_to_devstate_map[state] = this_devstate;
4392 }
4393 }
4394}
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
Definition: devicestate.c:263
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:869

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

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

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

2975{
2976 int is_valid = 0;
2977 switch (new_state) {
2978 case CC_AVAILABLE:
2979 ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to state %u? That should never happen.\n",
2980 agent->core_id, new_state);
2981 break;
2982 case CC_CALLER_OFFERED:
2983 if (current_state == CC_AVAILABLE) {
2984 is_valid = 1;
2985 }
2986 break;
2988 if (current_state == CC_CALLER_OFFERED ||
2989 (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) {
2990 is_valid = 1;
2991 }
2992 break;
2993 case CC_ACTIVE:
2994 if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) {
2995 is_valid = 1;
2996 }
2997 break;
2998 case CC_CALLEE_READY:
2999 if (current_state == CC_ACTIVE) {
3000 is_valid = 1;
3001 }
3002 break;
3003 case CC_CALLER_BUSY:
3004 if (current_state == CC_CALLEE_READY) {
3005 is_valid = 1;
3006 }
3007 break;
3008 case CC_RECALLING:
3009 if (current_state == CC_CALLEE_READY) {
3010 is_valid = 1;
3011 }
3012 break;
3013 case CC_COMPLETE:
3014 if (current_state == CC_RECALLING) {
3015 is_valid = 1;
3016 }
3017 break;
3018 case CC_FAILED:
3019 is_valid = 1;
3020 break;
3021 default:
3022 ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to unknown state %u\n",
3023 agent->core_id, new_state);
3024 break;
3025 }
3026
3027 return is_valid;
3028}
#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 4515 of file ccss.c.

4516{
4517 int *core_id = arg;
4518 struct cc_core_instance *core_instance = obj;
4519
4520 if (!core_id || (core_instance->core_id == *core_id)) {
4521 ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n");
4522 }
4523 return 0;
4524}

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

2500{
2501 unsigned long match_flags = MATCH_NO_REQUEST;
2502 struct ao2_iterator *dups_iter;
2503
2504 /*
2505 * Must remove the ref that was in cc_core_instances outside of
2506 * the container lock to prevent deadlock.
2507 */
2509 match_agent, caller, &match_flags, "Killing duplicate offers");
2510 if (dups_iter) {
2511 /* Now actually unref any duplicate offers by simply destroying the iterator. */
2512 ao2_iterator_destroy(dups_iter);
2513 }
2514}
@ 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 4624 of file ccss.c.

4625{
4626 int res;
4627
4631 "Create core instance container");
4632 if (!cc_core_instances) {
4634 }
4635
4638 generic_monitor_instance_list_hash_fn, NULL, generic_monitor_instance_list_cmp_fn,
4639 "Create generic monitor container");
4640 if (!generic_monitors) {
4642 }
4645 }
4648 }
4651 }
4656
4661
4662 /* Read the map and register the device state callback for generic agents */
4665
4667}
@ 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:4407
static enum ast_device_state ccss_device_state(const char *device_name)
Definition: ccss.c:606
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition: ccss.c:1168
static const int CC_CORE_INSTANCES_BUCKETS
Definition: ccss.c:331
static const char * ccreq_app
Definition: ccss.c:4226
static int cccancel_exec(struct ast_channel *chan, const char *data)
Definition: ccss.c:4279
static const char * cccancel_app
Definition: ccss.c:4277
static int cc_core_instance_cmp_fn(void *obj, void *arg, int flags)
Definition: ccss.c:429
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:1223
static const char * CC_LOGGER_LEVEL_NAME
Definition: ccss.c:135
static struct ast_cc_monitor_callbacks generic_monitor_cbs
Definition: ccss.c:1308
static int ccreq_exec(struct ast_channel *chan, const char *data)
Definition: ccss.c:4228
static void initialize_cc_max_requests(void)
Definition: ccss.c:4348
static struct ast_cli_entry cc_cli[]
Definition: ccss.c:4589
static int cc_core_instance_hash_fn(const void *obj, const int flags)
Definition: ccss.c:423
static struct ast_cc_agent_callbacks generic_agent_callbacks
Definition: ccss.c:2590
#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:394
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:2826
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition: pbx_app.c:104
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition: module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
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 498 of file ccss.c.

499{
500 struct cc_core_instance *core_instance = obj;
501 const char *name = arg;
502 unsigned long match_flags = *(unsigned long *)data;
503 int possible_match = 0;
504
506 possible_match = 1;
507 }
508
509 if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) {
510 possible_match = 1;
511 }
512
513 if (!possible_match) {
514 return 0;
515 }
516
517 if (!strcmp(core_instance->agent->device_name, name)) {
518 return CMP_MATCH | CMP_STOP;
519 }
520 return 0;
521}

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

749{
750 switch (policy) {
752 return "never";
754 return "native";
756 return "generic";
758 return "always";
759 default:
760 /* This should never happen... */
761 return "";
762 }
763}
@ 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 2675 of file ccss.c.

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

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

4453{
4454 int *cli_fd = arg;
4455 struct cc_core_instance *core_instance = obj;
4456
4457 ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name,
4458 cc_state_to_string(core_instance->current_state));
4459 AST_LIST_LOCK(core_instance->monitors);
4460 cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0);
4461 AST_LIST_UNLOCK(core_instance->monitors);
4462 return 0;
4463}

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

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

704{
705 if (!strcasecmp(value, "never")) {
706 return AST_CC_AGENT_NEVER;
707 } else if (!strcasecmp(value, "native")) {
708 return AST_CC_AGENT_NATIVE;
709 } else if (!strcasecmp(value, "generic")) {
711 } else {
712 ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value);
713 return AST_CC_AGENT_NEVER;
714 }
715}

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

718{
719 if (!strcasecmp(value, "never")) {
721 } else if (!strcasecmp(value, "native")) {
723 } else if (!strcasecmp(value, "generic")) {
725 } else if (!strcasecmp(value, "always")) {
727 } else {
728 ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value);
730 }
731}

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

3167{
3168 struct ast_cc_monitor *monitor_iter;
3169 AST_LIST_LOCK(core_instance->monitors);
3170 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3171 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3172 if (monitor_iter->callbacks->suspend(monitor_iter)) {
3174 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3175 monitor_iter->interface->device_name, 1);
3176 cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor");
3177 }
3178 }
3179 }
3181
3182 if (!has_device_monitors(core_instance)) {
3183 ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC");
3184 }
3185 AST_LIST_UNLOCK(core_instance->monitors);
3186}
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 4594 of file ccss.c.

4595{
4596 ast_devstate_prov_del("ccss");
4603
4604 if (cc_sched_context) {
4607 }
4610 }
4611 /* Note that core instances must be destroyed prior to the generic_monitors */
4612 if (cc_core_instances) {
4613 ao2_t_ref(cc_core_instances, -1, "Unref cc_core_instances container in cc_shutdown");
4615 }
4616 if (generic_monitors) {
4617 ao2_t_ref(generic_monitors, -1, "Unref generic_monitor container in cc_shutdown");
4619 }
4620
4621 return 0;
4622}
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1201
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1238
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:421
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:2884
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 3119 of file ccss.c.

3120{
3121 struct ast_cc_monitor *monitor_iter;
3122 AST_LIST_LOCK(core_instance->monitors);
3123 AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3124 if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3125 if (monitor_iter->callbacks->unsuspend(monitor_iter)) {
3127 cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3128 monitor_iter->interface->device_name, 1);
3129 cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor");
3130 }
3131 }
3132 }
3134
3135 if (!has_device_monitors(core_instance)) {
3136 ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC");
3137 }
3138 AST_LIST_UNLOCK(core_instance->monitors);
3139}
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 4674 of file ccss.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4674 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:4548
static char * handle_cc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: ccss.c:4482

Definition at line 4589 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 331 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 668 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 135 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 147 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 569 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 4277 of file ccss.c.

Referenced by load_module(), and unload_module().

◆ ccreq_app

const char* ccreq_app = "CallCompletionRequest"
static

Definition at line 4226 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 126 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 1859 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:1928
static void * dialed_cc_interfaces_duplicate(void *data)
Definition: ccss.c:1948

Definition at line 1973 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 2590 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 1308 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 143 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:3365
static void * cc_recall_ds_duplicate(void *data)
Definition: ccss.c:3351

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

◆ state

Definition at line 399 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_ari_transfer_message_create(), 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_incoming_ari_request(), 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 3246 of file ccss.c.

Referenced by cc_do_state_change().

◆ state_string

const char* state_string

Definition at line 400 of file ccss.c.