Asterisk - The Open Source Telephony Project  18.5.0
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_macro (struct ast_cc_config_params *config)
 Get the name of the callback_macro. 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_macro (struct ast_cc_config_params *config, const char *const value)
 Set the callback_macro name. 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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
struct cc_agent_backends cc_agent_backends = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct ast_cli_entry cc_cli []
 
static struct ao2_containercc_core_instances
 
static const int CC_CORE_INSTANCES_BUCKETS = 17
 
static struct ast_taskprocessorcc_core_taskprocessor
 
static const struct ast_cc_config_params cc_default_params
 
static int cc_logger_level
 
static const char * CC_LOGGER_LEVEL_NAME = "CC"
 
struct cc_monitor_backends cc_monitor_backends = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static int cc_request_count
 
static struct ast_sched_contextcc_sched_context
 
struct {
   enum ast_cc_service_type   service
 
   const char *   service_string
 
cc_service_to_string_map []
 
static enum ast_device_state cc_state_to_devstate_map []
 
struct {
   enum cc_state   state
 
   const char *   state_string
 
cc_state_to_string_map []
 
static const char * cccancel_app = "CallCompletionCancel"
 
static const char * ccreq_app = "CallCompletionRequest"
 
static int core_id_counter
 
static int dialed_cc_interface_counter
 
static const struct ast_datastore_info dialed_cc_interfaces_info
 
static struct ast_cc_agent_callbacks generic_agent_callbacks
 
static struct ast_cc_monitor_callbacks generic_monitor_cbs
 
struct ao2_containergeneric_monitors
 
static unsigned int global_cc_max_requests
 
static const struct ast_datastore_info recall_ds_info
 
static int(*const state_change_funcs [])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state)
 

Detailed Description

Call Completion Supplementary Services implementation.

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

Definition in file ccss.c.

Macro Definition Documentation

◆ CC_ACTIVE_DEVSTATE_DEFAULT

#define CC_ACTIVE_DEVSTATE_DEFAULT   AST_DEVICE_INUSE

Definition at line 552 of file ccss.c.

◆ CC_AVAILABLE_DEVSTATE_DEFAULT

#define CC_AVAILABLE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 549 of file ccss.c.

◆ CC_CALLEE_READY_DEVSTATE_DEFAULT

#define CC_CALLEE_READY_DEVSTATE_DEFAULT   AST_DEVICE_RINGING

Definition at line 553 of file ccss.c.

◆ CC_CALLER_BUSY_DEVSTATE_DEFAULT

#define CC_CALLER_BUSY_DEVSTATE_DEFAULT   AST_DEVICE_ONHOLD

Definition at line 554 of file ccss.c.

◆ CC_CALLER_OFFERED_DEVSTATE_DEFAULT

#define CC_CALLER_OFFERED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 550 of file ccss.c.

◆ CC_CALLER_REQUESTED_DEVSTATE_DEFAULT

#define CC_CALLER_REQUESTED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 551 of file ccss.c.

◆ CC_COMPLETE_DEVSTATE_DEFAULT

#define CC_COMPLETE_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 556 of file ccss.c.

◆ CC_FAILED_DEVSTATE_DEFAULT

#define CC_FAILED_DEVSTATE_DEFAULT   AST_DEVICE_NOT_INUSE

Definition at line 557 of file ccss.c.

◆ CC_MAX_AGENTS_DEFAULT

#define CC_MAX_AGENTS_DEFAULT   5

Definition at line 658 of file ccss.c.

◆ CC_MAX_MONITORS_DEFAULT

#define CC_MAX_MONITORS_DEFAULT   5

Definition at line 659 of file ccss.c.

◆ CC_OFFER_TIMER_DEFAULT

#define CC_OFFER_TIMER_DEFAULT   20 /* Seconds */

Definition at line 654 of file ccss.c.

◆ CC_RECALL_TIMER_DEFAULT

#define CC_RECALL_TIMER_DEFAULT   20 /* Seconds */

Definition at line 657 of file ccss.c.

◆ CC_RECALLING_DEVSTATE_DEFAULT

#define CC_RECALLING_DEVSTATE_DEFAULT   AST_DEVICE_RINGING

Definition at line 555 of file ccss.c.

◆ CCBS_AVAILABLE_TIMER_DEFAULT

#define CCBS_AVAILABLE_TIMER_DEFAULT   4800 /* Seconds */

Definition at line 656 of file ccss.c.

◆ CCNR_AVAILABLE_TIMER_DEFAULT

#define CCNR_AVAILABLE_TIMER_DEFAULT   7200 /* Seconds */

Definition at line 655 of file ccss.c.

◆ GLOBAL_CC_MAX_REQUESTS_DEFAULT

#define GLOBAL_CC_MAX_REQUESTS_DEFAULT   20

Definition at line 660 of file ccss.c.

Referenced by initialize_cc_max_requests().

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

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

◆ match_flags

Enumerator
MATCH_NO_REQUEST 
MATCH_REQUEST 

Definition at line 469 of file ccss.c.

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

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

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

682 {
683  struct ast_cc_config_params *params = __ast_malloc(sizeof(*params), file, line, function);
684 
685  if (!params) {
686  return NULL;
687  }
688 
690  return params;
691 }
#define NULL
Definition: resample.c:96
void ast_cc_default_config_params(struct ast_cc_config_params *params)
Set the specified CC config params to default values.
Definition: ccss.c:676
void * __ast_malloc(size_t size, const char *file, int lineno, const char *func) attribute_malloc
Definition: astmm.c:1660

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4703 of file ccss.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4703 of file ccss.c.

◆ agent_destroy()

static void agent_destroy ( void *  data)
static

Definition at line 2544 of file ccss.c.

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

Referenced by cc_agent_init().

2545 {
2546  struct ast_cc_agent *agent = data;
2547 
2548  if (agent->callbacks) {
2549  agent->callbacks->destructor(agent);
2550  }
2552 }
struct ast_cc_config_params * cc_params
Definition: ccss.h:859
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:693
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
void(* destructor)(struct ast_cc_agent *agent)
Destroy private data on the agent.
Definition: ccss.h:1072

◆ agent_policy_to_str()

static const char* agent_policy_to_str ( enum ast_cc_agent_policies  policy)
static

Definition at line 728 of file ccss.c.

References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, and AST_CC_AGENT_NEVER.

Referenced by ast_cc_get_param().

729 {
730  switch (policy) {
731  case AST_CC_AGENT_NEVER:
732  return "never";
733  case AST_CC_AGENT_NATIVE:
734  return "native";
736  return "generic";
737  default:
738  /* This should never happen... */
739  return "";
740  }
741 }

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

References CC_CALLER_REQUESTED, and cc_request_state_change().

Referenced by ccreq_exec(), and handle_cc_subscribe().

3777 {
3778  va_list ap;
3779  int res;
3780 
3781  va_start(ap, debug);
3783  va_end(ap);
3784  return res;
3785 }
static int debug
Global debug status.
Definition: res_xmpp.c:435
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3328
unsigned int core_id
Definition: ccss.h:849

◆ ast_cc_agent_callback()

struct ast_cc_agent* ast_cc_agent_callback ( int  flags,
ao2_callback_fn function,
void *  arg,
const char *const  type 
)

Call a callback on all agents of a specific type.

Since the container of CC core instances is private, and so are the items which the container contains, we have to provide an ao2_callback-like method so that a specific agent may be found or so that an operation can be made on all agents of a particular type. The first three arguments should be familiar to anyone who has used ao2_callback. The final argument is the type of agent you wish to have the callback called on.

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

Definition at line 456 of file ccss.c.

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

Referenced by find_sip_cc_agent_by_notify_uri(), find_sip_cc_agent_by_original_callid(), and find_sip_cc_agent_by_subscribe_uri().

457 {
458  struct cc_callback_helper helper = {.function = function, .args = args, .type = type};
459  struct cc_core_instance *core_instance;
460  if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper,
461  "Calling provided agent callback function"))) {
462  struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent");
463  cc_unref(core_instance, "agent callback done with the core_instance");
464  return agent;
465  }
466  return NULL;
467 }
static const char type[]
Definition: chan_ooh323.c:109
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
ao2_callback_fn * function
Definition: ccss.c:439
const char * args
#define NULL
Definition: resample.c:96
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1714
static int cc_agent_callback_helper(void *obj, void *args, int flags)
Definition: ccss.c:444
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
struct ast_cc_agent * agent
Definition: ccss.c:341

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

References CC_ACTIVE, and cc_request_state_change().

Referenced by cc_esc_publish_handler(), and generic_agent_devstate_cb().

3821 {
3822  va_list ap;
3823  int res;
3824 
3825  va_start(ap, debug);
3827  va_end(ap);
3828  return res;
3829 }
static int debug
Global debug status.
Definition: res_xmpp.c:435
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3328
unsigned int core_id
Definition: ccss.h:849

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

References CC_CALLER_BUSY, and cc_request_state_change().

Referenced by cc_esc_publish_handler(), cc_generic_agent_recall(), and sip_cc_agent_recall().

3810 {
3811  va_list ap;
3812  int res;
3813 
3814  va_start(ap, debug);
3816  va_end(ap);
3817  return res;
3818 }
static int debug
Global debug status.
Definition: res_xmpp.c:435
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3328
unsigned int core_id
Definition: ccss.h:849

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

References CC_RECALLING, and cc_request_state_change().

Referenced by generic_recall(), and get_destination().

3832 {
3833  va_list ap;
3834  int res;
3835 
3836  va_start(ap, debug);
3838  va_end(ap);
3839  return res;
3840 }
static int debug
Global debug status.
Definition: res_xmpp.c:435
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3328
unsigned int core_id
Definition: ccss.h:849

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

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

Referenced by load_module().

1240 {
1241  struct cc_agent_backend *backend = ast_calloc(1, sizeof(*backend));
1242 
1243  if (!backend) {
1244  return -1;
1245  }
1246 
1247  backend->callbacks = callbacks;
1251  return 0;
1252 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
struct cc_agent_backend * next
Definition: ccss.c:1233
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.c:1234
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740

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

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

Referenced by generic_recall(), and handle_request_invite().

3632 {
3633  struct ast_datastore *recall_datastore;
3634  struct cc_monitor_tree *interface_tree;
3635  struct ast_cc_monitor *monitor;
3636  struct cc_recall_ds_data *recall_data;
3637  struct ast_str *str = ast_str_create(64);
3638  int core_id;
3639 
3640  if (!str) {
3641  return -1;
3642  }
3643 
3644  ast_channel_lock(chan);
3645  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3646  ast_channel_unlock(chan);
3647  ast_free(str);
3648  return -1;
3649  }
3650  recall_data = recall_datastore->data;
3651  interface_tree = recall_data->interface_tree;
3652  core_id = recall_data->core_id;
3653  ast_channel_unlock(chan);
3654 
3655  AST_LIST_LOCK(interface_tree);
3656  monitor = AST_LIST_FIRST(interface_tree);
3657  build_cc_interfaces_chanvar(monitor, &str);
3658  AST_LIST_UNLOCK(interface_tree);
3659 
3660  pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3661  ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3662  core_id, ast_str_buffer(str));
3663 
3664  ast_free(str);
3665  return 0;
3666 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static const struct ast_datastore_info recall_ds_info
Definition: ccss.c:3399
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str **str)
Definition: ccss.c:3588
Structure for a data store object.
Definition: datastore.h:68
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:2404
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static unsigned int monitor
Definition: chan_phone.c:116
The "tree" of interfaces that is dialed.
Definition: ccss.c:324
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void * data
Definition: datastore.h:70
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3375
static int cc_logger_level
Definition: ccss.c:133
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

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

References args, ast_calloc, ast_free, ast_taskprocessor_push(), cc_status_response(), cc_unref(), cc_status_response_args::core_instance, cc_status_response_args::devstate, and find_cc_core_instance().

Referenced by cc_generic_agent_status_request(), and sip_cc_agent_status_request().

4094 {
4095  struct cc_status_response_args *args;
4096  struct cc_core_instance *core_instance;
4097  int res;
4098 
4099  args = ast_calloc(1, sizeof(*args));
4100  if (!args) {
4101  return -1;
4102  }
4103 
4104  core_instance = find_cc_core_instance(core_id);
4105  if (!core_instance) {
4106  ast_free(args);
4107  return -1;
4108  }
4109 
4110  args->core_instance = core_instance;
4111  args->devstate = devstate;
4112 
4114  if (res) {
4115  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4116  ast_free(args);
4117  }
4118  return res;
4119 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
const char * args
static int cc_status_response(void *data)
Definition: ccss.c:4072
struct cc_core_instance * core_instance
Definition: ccss.c:4068
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
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.
enum ast_device_state devstate
Definition: ccss.c:4069
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

◆ 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
Return values
0Successfully unregistered
-1Failure to unregister

Definition at line 1254 of file ccss.c.

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

Referenced by __unload_module(), and unload_module().

1255 {
1256  struct cc_agent_backend *backend;
1259  if (backend->callbacks == callbacks) {
1261  ast_free(backend);
1262  break;
1263  }
1264  }
1267 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
struct cc_agent_backend * next
Definition: ccss.c:1233
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.c:1234
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define ast_free(a)
Definition: astmm.h:182
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

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

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

1510 {
1511  struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data;
1512  int res;
1513  monitor->available_timer_id = -1;
1514  res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor");
1515  cc_unref(monitor, "Unref reference from scheduler\n");
1516  return res;
1517 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
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:3941
int core_id
Definition: ccss.h:528
static unsigned int monitor
Definition: chan_phone.c:116
struct ast_cc_interface * interface
Definition: ccss.h:514
int available_timer_id
Definition: ccss.h:547
char device_name[1]
Definition: ccss.h:839

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

References ast_calloc, AST_CONTROL_CC, AST_FRAME_CONTROL, ast_free, AST_MALLOCD_DATA, cc_build_payload(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, ast_frame::ptr, and ast_frame::subclass.

Referenced by ast_queue_cc_frame().

4180 {
4181  struct cc_control_payload *payload = ast_calloc(1, sizeof(*payload));
4182 
4183  if (!payload) {
4184  return -1;
4185  }
4186  if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) {
4187  /* Something screwed up, we can't make a frame with this */
4188  ast_free(payload);
4189  return -1;
4190  }
4191  frame->frametype = AST_FRAME_CONTROL;
4192  frame->subclass.integer = AST_CONTROL_CC;
4193  frame->data.ptr = payload;
4194  frame->datalen = sizeof(*payload);
4195  frame->mallocd = AST_MALLOCD_DATA;
4196  return 0;
4197 }
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:222
void * private_data
Private data allocated by the callee.
Definition: ccss.c:257
#define AST_MALLOCD_DATA
struct ast_frame_subclass subclass
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:4121
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:293
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:305
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
union ast_frame::@263 data
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:240
enum ast_frame_type frametype
enum ast_cc_service_type service
Definition: ccss.c:383

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

References AST_CC_CCBS, ast_handle_cc_control_frame(), call_destructor_with_no_monitor(), cc_build_payload(), and NULL.

Referenced by dial_exec_full().

4234 {
4235  struct cc_control_payload payload;
4236  if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) {
4237  /* Something screwed up. Don't try to handle this payload */
4239  return;
4240  }
4241  ast_handle_cc_control_frame(inbound, NULL, &payload);
4242 }
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:222
void * private_data
Private data allocated by the callee.
Definition: ccss.c:257
static void call_destructor_with_no_monitor(const char *const monitor_type, void *private_data)
Definition: ccss.c:2216
#define NULL
Definition: resample.c:96
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:4121
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:293
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:305
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:2316
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:240

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

References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CC_CCBS, AST_CC_GENERIC_MONITOR_TYPE, AST_CC_MONITOR_GENERIC, ast_channel_get_cc_config_params(), ast_channel_get_device_name(), ast_channel_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().

4200 {
4202  struct cc_control_payload payload;
4203  struct ast_cc_config_params *cc_params;
4204 
4206  /* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call
4207  * failing is something other than busy or congestion
4208  */
4209  return;
4210  }
4211 
4212  cc_params = ast_channel_get_cc_config_params(outgoing);
4213  if (!cc_params) {
4214  return;
4215  }
4217  /* This sort of CCBS only works if using generic CC. For native, we would end up sending
4218  * a CC request for a non-existent call. The far end will reject this every time
4219  */
4220  return;
4221  }
4222 
4223  ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
4224  if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
4225  dialstring, AST_CC_CCBS, NULL, &payload)) {
4226  /* Something screwed up, we can't make a frame with this */
4227  return;
4228  }
4229  ast_handle_cc_control_frame(incoming, outgoing, &payload);
4230 }
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:222
#define NULL
Definition: resample.c:96
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:4121
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:10675
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:883
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:293
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:2316
#define AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:489
#define AST_CHANNEL_NAME
Definition: channel.h:172
int ast_channel_hangupcause(const struct ast_channel *chan)
#define AST_CAUSE_BUSY
Definition: causes.h:148
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:10697
#define AST_CAUSE_CONGESTION
Definition: causes.h:152

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

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_macrocontext(), ast_channel_macroexten(), 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, dialed_cc_interfaces::core_id, ast_datastore::data, dialed_cc_interfaces::dial_parent_id, ast_cc_monitor::id, dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, interfaces, monitor, NULL, and S_OR.

Referenced by dial_exec_full().

2410 {
2411  /* There are three situations to deal with here:
2412  *
2413  * 1. The channel does not have a dialed_cc_interfaces datastore on
2414  * it. This means that this is the first time that Dial has
2415  * been called. We need to create/initialize the datastore.
2416  *
2417  * 2. The channel does have a cc_interface datastore on it and
2418  * the "ignore" indicator is 0. This means that a Local channel
2419  * was called by a "parent" dial. We can check the datastore's
2420  * parent field to see who the root of this particular dial tree
2421  * is.
2422  *
2423  * 3. The channel does have a cc_interface datastore on it and
2424  * the "ignore" indicator is 1. This means that a second Dial call
2425  * is being made from an extension. In this case, we do not
2426  * want to make any additions/modifications to the datastore. We
2427  * will instead set a flag to indicate that CCSS is completely
2428  * disabled for this Dial attempt.
2429  */
2430 
2431  struct ast_datastore *cc_interfaces_datastore;
2433  struct ast_cc_monitor *monitor;
2434  struct ast_cc_config_params *cc_params;
2435 
2436  ast_channel_lock(chan);
2437 
2438  cc_params = ast_channel_get_cc_config_params(chan);
2439  if (!cc_params) {
2440  ast_channel_unlock(chan);
2441  return -1;
2442  }
2443  if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) {
2444  /* We can't offer CC to this caller anyway, so don't bother with CC on this call
2445  */
2446  *ignore_cc = 1;
2447  ast_channel_unlock(chan);
2448  ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", ast_channel_name(chan));
2449  return 0;
2450  }
2451 
2452  if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2453  /* Situation 1 has occurred */
2454  ast_channel_unlock(chan);
2455  return cc_interfaces_datastore_init(chan);
2456  }
2457  interfaces = cc_interfaces_datastore->data;
2458  ast_channel_unlock(chan);
2459 
2460  if (interfaces->ignore) {
2461  /* Situation 3 has occurred */
2462  *ignore_cc = 1;
2463  ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n");
2464  return 0;
2465  }
2466 
2467  /* Situation 2 has occurred */
2469  S_OR(ast_channel_macrocontext(chan), ast_channel_context(chan)), interfaces->dial_parent_id))) {
2470  return -1;
2471  }
2472  monitor->core_id = interfaces->core_id;
2473  AST_LIST_LOCK(interfaces->interface_tree);
2474  cc_ref(monitor, "monitor tree's reference to the monitor");
2475  AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
2476  AST_LIST_UNLOCK(interfaces->interface_tree);
2477  interfaces->dial_parent_id = monitor->id;
2478  cc_unref(monitor, "Unref monitor's allocation reference");
2479  return 0;
2480 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
unsigned int id
Definition: ccss.h:519
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1989
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:2089
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
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:10675
static struct ao2_container * interfaces
Container for registered format interfaces.
Definition: format.c:65
int core_id
Definition: ccss.h:528
const char * ast_channel_exten(const struct ast_channel *chan)
static int cc_interfaces_datastore_init(struct ast_channel *chan)
Definition: ccss.c:2138
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static unsigned int monitor
Definition: chan_phone.c:116
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1929
void * data
Definition: datastore.h:70
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:866
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
unsigned int dial_parent_id
Definition: ccss.c:1902
const char * ast_channel_macrocontext(const struct ast_channel *chan)
static int cc_logger_level
Definition: ccss.c:133
const char * ast_channel_macroexten(const struct ast_channel *chan)

◆ 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
Always0, I guess.

Definition at line 4244 of file ccss.c.

References ast_get_channel_tech(), and ast_channel_tech::cc_callback.

Referenced by dial_exec_full().

4245 {
4246  const struct ast_channel_tech *chantech = ast_get_channel_tech(tech);
4247 
4248  if (chantech && chantech->cc_callback) {
4249  chantech->cc_callback(inbound, dest, callback);
4250  }
4251 
4252  return 0;
4253 }
const struct ast_channel_tech * ast_get_channel_tech(const char *name)
Get a channel technology structure by name.
Definition: channel.c:592
int(* cc_callback)(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
Call a function with cc parameters as a function parameter.
Definition: channel.h:828
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629

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

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

Referenced by wait_for_answer().

3843 {
3844  struct ast_datastore *recall_datastore;
3845  struct cc_recall_ds_data *recall_data;
3846  int core_id;
3847  va_list ap;
3848  int res;
3849 
3850  ast_channel_lock(chan);
3851  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3852  /* Silly! Why did you call this function if there's no recall DS? */
3853  ast_channel_unlock(chan);
3854  return -1;
3855  }
3856  recall_data = recall_datastore->data;
3857  if (recall_data->nested || recall_data->ignore) {
3858  /* If this is being called from a nested Dial, it is too
3859  * early to determine if the recall has actually completed.
3860  * The outermost dial is the only one with the authority to
3861  * declare the recall to be complete.
3862  *
3863  * Similarly, if this function has been called when the
3864  * recall has progressed beyond the first dial, this is not
3865  * a legitimate time to declare the recall to be done. In fact,
3866  * that should have been done already.
3867  */
3868  ast_channel_unlock(chan);
3869  return -1;
3870  }
3871  core_id = recall_data->core_id;
3872  ast_channel_unlock(chan);
3873  va_start(ap, debug);
3874  res = cc_request_state_change(CC_COMPLETE, core_id, debug, ap);
3875  va_end(ap);
3876  return res;
3877 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static int debug
Global debug status.
Definition: res_xmpp.c:435
static const struct ast_datastore_info recall_ds_info
Definition: ccss.c:3399
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3328
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * data
Definition: datastore.h:70

◆ 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
Return values
void

Definition at line 693 of file ccss.c.

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(), setup_dahdi(), sip_destroy_peer(), and sip_pvt_dtor().

694 {
695  ast_free(params);
696 }
#define ast_free(a)
Definition: astmm.h:182

◆ 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
Returns
Nothing

Definition at line 861 of file ccss.c.

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

862 {
863  *dest = *src;
864 }

◆ 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.
Returns
Nothing

Definition at line 676 of file ccss.c.

References cc_default_params.

Referenced by __ast_cc_config_params_init().

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

◆ 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
Return values
void

Definition at line 2005 of file ccss.c.

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

Referenced by dial_exec_full().

2006 {
2007  struct ast_datastore *cc_datastore;
2008  struct dialed_cc_interfaces *cc_interfaces;
2009  struct ast_cc_monitor *monitor;
2010  struct extension_monitor_pvt *extension_pvt;
2011  struct extension_child_dialstring *child_dialstring;
2012  struct cc_monitor_tree *interface_tree;
2013  int id;
2014 
2015  ast_channel_lock(incoming);
2016  if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) {
2017  ast_channel_unlock(incoming);
2018  return;
2019  }
2020 
2021  cc_interfaces = cc_datastore->data;
2022  interface_tree = cc_interfaces->interface_tree;
2023  id = cc_interfaces->dial_parent_id;
2024  ast_channel_unlock(incoming);
2025 
2026  AST_LIST_LOCK(interface_tree);
2027  AST_LIST_TRAVERSE(interface_tree, monitor, next) {
2028  if (monitor->id == id) {
2029  break;
2030  }
2031  }
2032 
2033  if (!monitor) {
2034  AST_LIST_UNLOCK(interface_tree);
2035  return;
2036  }
2037 
2038  extension_pvt = monitor->private_data;
2039  if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) {
2040  AST_LIST_UNLOCK(interface_tree);
2041  return;
2042  }
2043  ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring));
2044  ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name));
2045  child_dialstring->is_valid = 1;
2046  AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next);
2047  AST_LIST_UNLOCK(interface_tree);
2048 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
unsigned int id
Definition: ccss.h:519
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition: ccss.c:1810
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1989
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
struct extension_monitor_pvt::@366 child_dialstrings
char device_name[AST_CHANNEL_NAME]
The name of the device being dialed.
Definition: ccss.c:1795
static unsigned int monitor
Definition: chan_phone.c:116
The "tree" of interfaces that is dialed.
Definition: ccss.c:324
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1929
void * data
Definition: datastore.h:70
char original_dialstring[AST_CHANNEL_NAME]
the original dialstring used to call a particular device
Definition: ccss.c:1776
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
Data regarding an extension monitor&#39;s child&#39;s dialstrings.
Definition: ccss.c:1760
Private data for an extension monitor.
Definition: ccss.c:1817
enum queue_result id
Definition: app_queue.c:1507
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:561
unsigned int dial_parent_id
Definition: ccss.c:1902

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

References CC_FAILED, and cc_request_state_change().

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

3880 {
3881  va_list ap;
3882  int res;
3883 
3884  va_start(ap, debug);
3885  res = cc_request_state_change(CC_FAILED, core_id, debug, ap);
3886  va_end(ap);
3887  return res;
3888 }
static int debug
Global debug status.
Definition: res_xmpp.c:435
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3328

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

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

Referenced by sip_handle_cc().

2488 {
2489  struct ast_datastore *datastore;
2490  struct dialed_cc_interfaces *cc_interfaces;
2491  int core_id_return;
2492 
2493  ast_channel_lock(chan);
2494  if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2495  ast_channel_unlock(chan);
2496  return -1;
2497  }
2498 
2499  cc_interfaces = datastore->data;
2500  core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id;
2501  ast_channel_unlock(chan);
2502  return core_id_return;
2503 
2504 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1989
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * data
Definition: datastore.h:70

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

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

Referenced by sip_call().

3520 {
3521  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3522  struct ast_cc_monitor *monitor_iter;
3523 
3524  if (!core_instance) {
3525  return NULL;
3526  }
3527 
3528  AST_LIST_LOCK(core_instance->monitors);
3529  AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
3530  if (!strcmp(monitor_iter->interface->device_name, device_name)) {
3531  /* Found a monitor. */
3532  cc_ref(monitor_iter, "Hand the requester of the monitor a reference");
3533  break;
3534  }
3535  }
3536  AST_LIST_UNLOCK(core_instance->monitors);
3537  cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id");
3538  return monitor_iter;
3539 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
struct ast_cc_monitor * next
Definition: ccss.h:562
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define NULL
Definition: resample.c:96
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_cc_interface * interface
Definition: ccss.h:514
char device_name[1]
Definition: ccss.h:839

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

References agent_policy_to_str(), ast_copy_string(), ast_get_cc_agent_dialstring(), ast_get_cc_agent_policy(), ast_get_cc_callback_macro(), ast_get_cc_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, LOG_WARNING, monitor_policy_to_str(), NULL, and value.

Referenced by acf_cc_read().

761 {
762  const char *value = NULL;
763 
764  if (!strcasecmp(name, "cc_callback_macro")) {
765  value = ast_get_cc_callback_macro(params);
766  } else if (!strcasecmp(name, "cc_callback_sub")) {
767  value = ast_get_cc_callback_sub(params);
768  } else if (!strcasecmp(name, "cc_agent_policy")) {
770  } else if (!strcasecmp(name, "cc_monitor_policy")) {
772  } else if (!strcasecmp(name, "cc_agent_dialstring")) {
773  value = ast_get_cc_agent_dialstring(params);
774  }
775  if (value) {
776  ast_copy_string(buf, value, buf_len);
777  return 0;
778  }
779 
780  /* The rest of these are all ints of some sort and require some
781  * snprintf-itude
782  */
783 
784  if (!strcasecmp(name, "cc_offer_timer")) {
785  snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params));
786  } else if (!strcasecmp(name, "ccnr_available_timer")) {
787  snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params));
788  } else if (!strcasecmp(name, "ccbs_available_timer")) {
789  snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params));
790  } else if (!strcasecmp(name, "cc_max_agents")) {
791  snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params));
792  } else if (!strcasecmp(name, "cc_max_monitors")) {
793  snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params));
794  } else if (!strcasecmp(name, "cc_recall_timer")) {
795  snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params));
796  } else {
797  ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
798  return -1;
799  }
800 
801  return 0;
802 }
unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
Get the ccnr_available_timer.
Definition: ccss.c:915
unsigned int ast_get_cc_recall_timer(struct ast_cc_config_params *config)
Get the cc_recall_timer.
Definition: ccss.c:930
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
static const char * monitor_policy_to_str(enum ast_cc_monitor_policies policy)
Definition: ccss.c:743
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:883
const char * ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
Get the cc_agent_dialstring.
Definition: ccss.c:960
const char * ast_get_cc_callback_macro(struct ast_cc_config_params *config)
Get the name of the callback_macro.
Definition: ccss.c:994
static const char name[]
Definition: cdr_mysql.c:74
static const char * agent_policy_to_str(enum ast_cc_agent_policies policy)
Definition: ccss.c:728
unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
Get the cc_max_agents.
Definition: ccss.c:974
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition: ccss.c:984
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:866
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_get_cc_callback_sub(struct ast_cc_config_params *config)
Get the name of the callback subroutine.
Definition: ccss.c:999
unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
Get the cc_offer_timer.
Definition: ccss.c:900
unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
Get the ccbs_available_timer.
Definition: ccss.c:945

◆ 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.

Referenced by build_peer(), and process_dahdi().

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_macro") ||
856  !strcasecmp(name, "cc_callback_sub") ||
857  !strcasecmp(name, "cc_agent_dialstring") ||
858  !strcasecmp(name, "cc_recall_timer"));
859 }
static const char name[]
Definition: cdr_mysql.c:74

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

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

Referenced by cc_core_init_instance(), sip_call(), and wait_for_answer().

3439 {
3440  struct ast_datastore *recall_datastore;
3441  struct cc_recall_ds_data *recall_data;
3442  struct cc_monitor_tree *interface_tree;
3443  char device_name[AST_CHANNEL_NAME];
3444  struct ast_cc_monitor *device_monitor;
3445  int core_id_candidate;
3446 
3447  ast_assert(core_id != NULL);
3448 
3449  *core_id = -1;
3450 
3451  ast_channel_lock(chan);
3452  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3453  /* Obviously not a recall if the datastore isn't present */
3454  ast_channel_unlock(chan);
3455  return 0;
3456  }
3457 
3458  recall_data = recall_datastore->data;
3459 
3460  if (recall_data->ignore) {
3461  /* Though this is a recall, the call to this particular interface is not part of the
3462  * recall either because this is a call forward or because this is not the first
3463  * invocation of Dial during this call
3464  */
3465  ast_channel_unlock(chan);
3466  return 0;
3467  }
3468 
3469  if (!recall_data->nested) {
3470  /* If the nested flag is not set, then this means that
3471  * the channel passed to this function is the caller making
3472  * the recall. This means that we shouldn't look through
3473  * the monitor tree for the channel because it shouldn't be
3474  * there. However, this is a recall though, so return true.
3475  */
3476  *core_id = recall_data->core_id;
3477  ast_channel_unlock(chan);
3478  return 1;
3479  }
3480 
3481  if (ast_strlen_zero(monitor_type)) {
3482  /* If someone passed a NULL or empty monitor type, then it is clear
3483  * the channel they passed in was an incoming channel, and so searching
3484  * the list of dialed interfaces is not going to be helpful. Just return
3485  * false immediately.
3486  */
3487  ast_channel_unlock(chan);
3488  return 0;
3489  }
3490 
3491  interface_tree = recall_data->interface_tree;
3492  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
3493  /* We grab the value of the recall_data->core_id so that we
3494  * can unlock the channel before we start looking through the
3495  * interface list. That way we don't have to worry about a possible
3496  * clash between the channel lock and the monitor tree lock.
3497  */
3498  core_id_candidate = recall_data->core_id;
3499  ast_channel_unlock(chan);
3500 
3501  /*
3502  * Now we need to find out if the channel device name
3503  * is in the list of interfaces in the called tree.
3504  */
3505  AST_LIST_LOCK(interface_tree);
3506  AST_LIST_TRAVERSE(interface_tree, device_monitor, next) {
3507  if (!strcmp(device_monitor->interface->device_name, device_name) &&
3508  !strcmp(device_monitor->interface->monitor_type, monitor_type)) {
3509  /* BOOM! Device is in the tree! We have a winner! */
3510  *core_id = core_id_candidate;
3511  AST_LIST_UNLOCK(interface_tree);
3512  return 1;
3513  }
3514  }
3515  AST_LIST_UNLOCK(interface_tree);
3516  return 0;
3517 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
struct ast_cc_monitor * next
Definition: ccss.h:562
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static const struct ast_datastore_info recall_ds_info
Definition: ccss.c:3399
#define ast_assert(a)
Definition: utils.h:695
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
int core_id
Definition: ccss.h:528
The "tree" of interfaces that is dialed.
Definition: ccss.c:324
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define AST_CHANNEL_NAME
Definition: channel.h:172
const char * monitor_type
The type of monitor that should be used for this interface.
Definition: ccss.h:830
struct ast_cc_interface * interface
Definition: ccss.h:514
void * data
Definition: datastore.h:70
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:10697
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3375
char device_name[1]
Definition: ccss.h:839

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

References CC_CALLEE_READY, and cc_request_state_change().

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

3799 {
3800  va_list ap;
3801  int res;
3802 
3803  va_start(ap, debug);
3805  va_end(ap);
3806  return res;
3807 }
static int debug
Global debug status.
Definition: res_xmpp.c:435
int core_id
Definition: ccss.h:528
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3328

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

References ao2_t_callback, ast_log_dynamic_level, 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().

4369 {
4370  struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,};
4371 
4372  ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents");
4373  ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count);
4374  return data.count;
4375 }
static const char type[]
Definition: chan_ooh323.c:109
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
static int count_monitors_cb(void *obj, void *arg, int flags)
Definition: ccss.c:4348
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1714
static const char name[]
Definition: cdr_mysql.c:74
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
static int cc_logger_level
Definition: ccss.c:133
const char * device_name
Definition: ccss.c:4343

◆ 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
Returns
void

Definition at line 3941 of file ccss.c.

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

Referenced by ast_cc_available_timer_expire(), cc_handle_publish_error(), and handle_response_subscribe().

3942 {
3943  struct ast_cc_monitor_failure_data *failure_data;
3944  int res;
3945  va_list ap;
3946 
3947  if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) {
3948  return -1;
3949  }
3950 
3951  if (!(failure_data->device_name = ast_strdup(monitor_name))) {
3952  ast_free(failure_data);
3953  return -1;
3954  }
3955 
3956  va_start(ap, debug);
3957  if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) {
3958  va_end(ap);
3959  ast_free((char *)failure_data->device_name);
3960  ast_free(failure_data);
3961  return -1;
3962  }
3963  va_end(ap);
3964 
3965  failure_data->core_id = core_id;
3966 
3968  if (res) {
3969  ast_free((char *)failure_data->device_name);
3970  ast_free((char *)failure_data->debug);
3971  ast_free(failure_data);
3972  }
3973  return res;
3974 }
static int debug
Global debug status.
Definition: res_xmpp.c:435
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
Definition: astmm.h:280
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
const char * device_name
Definition: ccss.c:3891
static int cc_monitor_failed(void *data)
Definition: ccss.c:3896
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

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

References ast_taskprocessor_push(), cc_party_b_free(), cc_unref(), and find_cc_core_instance().

4052 {
4053  int res;
4054  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4055 
4056  if (!core_instance) {
4057  return -1;
4058  }
4059 
4061  if (res) {
4062  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4063  }
4064  return res;
4065 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static int cc_party_b_free(void *data)
Definition: ccss.c:4039
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

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

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

Referenced by load_module().

1185 {
1186  struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend));
1187 
1188  if (!backend) {
1189  return -1;
1190  }
1191 
1192  backend->callbacks = callbacks;
1193 
1197  return 0;
1198 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.c:1179
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct cc_monitor_backend * next
Definition: ccss.c:1178
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740

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

References CC_ACTIVE, and cc_request_state_change().

Referenced by cc_generic_monitor_request_cc(), cc_stop_ringing(), and handle_cc_notify().

3788 {
3789  va_list ap;
3790  int res;
3791 
3792  va_start(ap, debug);
3793  res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3794  va_end(ap);
3795  return res;
3796 }
static int debug
Global debug status.
Definition: res_xmpp.c:435
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3328

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

References ast_taskprocessor_push(), cc_status_request(), cc_unref(), and find_cc_core_instance().

3987 {
3988  int res;
3989  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3990 
3991  if (!core_instance) {
3992  return -1;
3993  }
3994 
3996  if (res) {
3997  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3998  }
3999  return res;
4000 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
static int cc_status_request(void *data)
Definition: ccss.c:3976
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

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

References ast_taskprocessor_push(), cc_stop_ringing(), cc_unref(), and find_cc_core_instance().

4024 {
4025  int res;
4026  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
4027 
4028  if (!core_instance) {
4029  return -1;
4030  }
4031 
4033  if (res) {
4034  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
4035  }
4036  return res;
4037 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
static int cc_stop_ringing(void *data)
Definition: ccss.c:4002
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

◆ 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
Return values
0Successfully unregistered
-1Failure to unregister

Definition at line 1217 of file ccss.c.

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

Referenced by __unload_module(), and unload_module().

1218 {
1219  struct cc_monitor_backend *backend;
1222  if (backend->callbacks == callbacks) {
1224  ast_free(backend);
1225  break;
1226  }
1227  }
1230 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.c:1179
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define ast_free(a)
Definition: astmm.h:182
struct cc_monitor_backend * next
Definition: ccss.c:1178
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

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

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

Referenced by ast_hangup().

3752 {
3753  int core_id;
3754  int res = -1;
3755  struct ast_datastore *datastore;
3756  struct dialed_cc_interfaces *cc_interfaces;
3757  char cc_is_offerable;
3758 
3759  ast_channel_lock(caller_chan);
3760  if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) {
3761  ast_channel_unlock(caller_chan);
3762  return res;
3763  }
3764 
3765  cc_interfaces = datastore->data;
3766  cc_is_offerable = cc_interfaces->is_original_caller;
3767  core_id = cc_interfaces->core_id;
3768  ast_channel_unlock(caller_chan);
3769 
3770  if (cc_is_offerable) {
3771  res = cc_offer(core_id, "CC offered to caller %s", ast_channel_name(caller_chan));
3772  }
3773  return res;
3774 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1989
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
char is_original_caller
Definition: ccss.c:1925
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static int cc_offer(const int core_id, const char *const debug,...)
Definition: ccss.c:3740
void * data
Definition: datastore.h:70
const char * ast_channel_name(const struct ast_channel *chan)

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

References cc_request_count, and global_cc_max_requests.

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

2483 {
2485 }
static unsigned int global_cc_max_requests
Definition: ccss.c:137
static int cc_request_count
Definition: ccss.c:141

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

References ast_log, ast_set_cc_agent_dialstring(), ast_set_cc_agent_policy(), ast_set_cc_callback_macro(), ast_set_cc_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, str_to_agent_policy(), and str_to_monitor_policy().

Referenced by acf_cc_write(), build_peer(), and process_dahdi().

806 {
807  unsigned int value_as_uint;
808  if (!strcasecmp(name, "cc_agent_policy")) {
810  } else if (!strcasecmp(name, "cc_monitor_policy")) {
812  } else if (!strcasecmp(name, "cc_agent_dialstring")) {
814  } else if (!strcasecmp(name, "cc_callback_macro")) {
816  return 0;
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 }
void ast_set_cc_callback_sub(struct ast_cc_config_params *config, const char *const value)
Set the callback subroutine name.
Definition: ccss.c:1014
void ast_set_cc_agent_dialstring(struct ast_cc_config_params *config, const char *const value)
Set the cc_agent_dialstring.
Definition: ccss.c:965
static enum ast_cc_monitor_policies str_to_monitor_policy(const char *const value)
Definition: ccss.c:712
void ast_set_ccbs_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccbs_available_timer.
Definition: ccss.c:950
#define LOG_WARNING
Definition: logger.h:274
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:888
void ast_set_cc_max_monitors(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_monitors.
Definition: ccss.c:989
int value
Definition: syslog.c:37
void ast_set_cc_offer_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_offer_timer.
Definition: ccss.c:905
#define ast_log
Definition: astobj2.c:42
static enum ast_cc_agent_policies str_to_agent_policy(const char *const value)
Definition: ccss.c:698
void ast_set_ccnr_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccnr_available_timer.
Definition: ccss.c:920
static const char name[]
Definition: cdr_mysql.c:74
void ast_set_cc_recall_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_recall_timer.
Definition: ccss.c:935
void ast_set_cc_max_agents(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_agents.
Definition: ccss.c:979
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:871
void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char *const value)
Set the callback_macro name.
Definition: ccss.c:1004

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

References ast_cc_config_params::cc_agent_dialstring.

Referenced by ast_cc_get_param().

961 {
962  return config->cc_agent_dialstring;
963 }
char cc_agent_dialstring[AST_MAX_EXTENSION]
Definition: ccss.c:172

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

References ast_cc_config_params::cc_agent_policy.

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

867 {
868  return config->cc_agent_policy;
869 }
enum ast_cc_agent_policies cc_agent_policy
Definition: ccss.c:162

◆ ast_get_cc_callback_macro()

const char* ast_get_cc_callback_macro ( struct ast_cc_config_params config)

Get the name of the callback_macro.

Since
1.8
Parameters
configThe configuration to retrieve the callback_macro from
Returns
The callback_macro name

Definition at line 994 of file ccss.c.

References ast_cc_config_params::cc_callback_macro.

Referenced by ast_cc_get_param(), and generic_recall().

995 {
996  return config->cc_callback_macro;
997 }
char cc_callback_macro[AST_MAX_EXTENSION]
Definition: ccss.c:170

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

References ast_cc_config_params::cc_callback_sub.

Referenced by ast_cc_get_param(), and generic_recall().

1000 {
1001  return config->cc_callback_sub;
1002 }
char cc_callback_sub[AST_MAX_EXTENSION]
Definition: ccss.c:171

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

References ast_cc_config_params::cc_max_agents.

Referenced by ast_cc_get_param(), and cc_core_init_instance().

975 {
976  return config->cc_max_agents;
977 }
unsigned int cc_max_agents
Definition: ccss.c:168

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

References ast_cc_config_params::cc_max_monitors.

Referenced by ast_cc_get_param(), and ast_queue_cc_frame().

985 {
986  return config->cc_max_monitors;
987 }
unsigned int cc_max_monitors
Definition: ccss.c:169

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

References ast_cc_config_params::cc_monitor_policy.

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

884 {
885  return config->cc_monitor_policy;
886 }
enum ast_cc_monitor_policies cc_monitor_policy
Definition: ccss.c:163

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

References ast_cc_config_params::cc_offer_timer.

Referenced by ast_cc_get_param(), cc_generic_agent_start_offer_timer(), and sip_cc_agent_start_offer_timer().

901 {
902  return config->cc_offer_timer;
903 }
unsigned int cc_offer_timer
Definition: ccss.c:164

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

References ast_cc_config_params::cc_recall_timer.

Referenced by ast_cc_get_param(), and generic_recall().

931 {
932  return config->cc_recall_timer;
933 }
unsigned int cc_recall_timer
Definition: ccss.c:167

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

References ast_cc_config_params::ccbs_available_timer.

Referenced by ast_cc_get_param(), cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().

946 {
947  return config->ccbs_available_timer;
948 }
unsigned int ccbs_available_timer
Definition: ccss.c:166

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

References ast_cc_config_params::ccnr_available_timer.

Referenced by ast_cc_get_param(), cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().

916 {
917  return config->ccnr_available_timer;
918 }
unsigned int ccnr_available_timer
Definition: ccss.c:165

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

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_CC, ast_indicate_data(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_log_dynamic_level, call_destructor_with_no_monitor(), cc_core_init_instance(), cc_device_monitor_init(), cc_extension_monitor_change_is_valid(), cc_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, cc_control_payload::device_name, ast_cc_interface::device_name, cc_control_payload::dialstring, ast_cc_monitor::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, monitor, 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().

2317 {
2318  char *device_name;
2319  char *dialstring;
2320  struct ast_cc_monitor *monitor;
2321  struct ast_datastore *cc_datastore;
2322  struct dialed_cc_interfaces *cc_interfaces;
2323  struct cc_control_payload *cc_data = frame_data;
2324  struct cc_core_instance *core_instance;
2325 
2326  device_name = cc_data->device_name;
2327  dialstring = cc_data->dialstring;
2328 
2329  ast_channel_lock(inbound);
2330  if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
2331  ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name);
2332  ast_channel_unlock(inbound);
2334  return;
2335  }
2336 
2337  cc_interfaces = cc_datastore->data;
2338 
2339  if (cc_interfaces->ignore) {
2340  ast_channel_unlock(inbound);
2342  return;
2343  }
2344 
2345  if (!cc_interfaces->is_original_caller) {
2346  /* If the is_original_caller is not set on the *inbound* channel, then
2347  * it must be a local channel. As such, we do not want to create a core instance
2348  * or an agent for the local channel. Instead, we want to pass this along to the
2349  * other side of the local channel so that the original caller can benefit.
2350  */
2351  ast_channel_unlock(inbound);
2352  ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data));
2353  return;
2354  }
2355 
2356  core_instance = find_cc_core_instance(cc_interfaces->core_id);
2357  if (!core_instance) {
2358  core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree,
2359  cc_interfaces->core_id, cc_data);
2360  if (!core_instance) {
2361  cc_interfaces->ignore = 1;
2362  ast_channel_unlock(inbound);
2364  return;
2365  }
2366  }
2367 
2368  ast_channel_unlock(inbound);
2369 
2370  /* Yeah this kind of sucks, but luckily most people
2371  * aren't dialing thousands of interfaces on every call
2372  *
2373  * This traversal helps us to not create duplicate monitors in
2374  * case a device queues multiple CC control frames.
2375  */
2376  AST_LIST_LOCK(cc_interfaces->interface_tree);
2377  AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) {
2378  if (!strcmp(monitor->interface->device_name, device_name)) {
2379  ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n",
2380  core_instance->core_id, device_name);
2381  AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2382  cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2384  return;
2385  }
2386  }
2387  AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2388 
2389  if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) {
2390  ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name);
2391  cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2393  return;
2394  }
2395 
2396  AST_LIST_LOCK(cc_interfaces->interface_tree);
2397  cc_ref(monitor, "monitor tree's reference to the monitor");
2398  AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next);
2399  AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2400 
2401  cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0);
2402 
2403  cc_publish_available(cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service));
2404 
2405  cc_unref(core_instance, "Done with core_instance after handling CC control frame");
2406  cc_unref(monitor, "Unref reference from allocating monitor");
2407 }
static const char * cc_service_to_string(enum ast_cc_service_type service)
Definition: ccss.c:412
#define ast_channel_lock(chan)
Definition: channel.h:2945
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:222
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
void * private_data
Private data allocated by the callee.
Definition: ccss.c:257
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
#define LOG_WARNING
Definition: logger.h:274
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1989
static void call_destructor_with_no_monitor(const char *const monitor_type, void *private_data)
Definition: ccss.c:2216
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:4698
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
static void cc_publish_available(int core_id, const char *callee, const char *service)
Definition: ccss.c:1063
Structure for a data store object.
Definition: datastore.h:68
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:2050
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:2404
#define NULL
Definition: resample.c:96
unsigned int parent_id
Definition: ccss.h:524
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:2250
#define ast_log
Definition: astobj2.c:42
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:2940
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:293
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:305
char is_original_caller
Definition: ccss.c:1925
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static unsigned int monitor
Definition: chan_phone.c:116
enum ast_cc_service_type service
Service offered by the endpoint.
Definition: ccss.c:266
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct ast_cc_interface * interface
Definition: ccss.h:514
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1929
void * data
Definition: datastore.h:70
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:240
char device_name[1]
Definition: ccss.h:839
static int cc_logger_level
Definition: ccss.c:133

◆ 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.
Return values
void

Definition at line 3720 of file ccss.c.

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

Referenced by dial_exec_full(), and do_forward().

3721 {
3722  struct ast_datastore *cc_datastore;
3723  struct ast_datastore *cc_recall_datastore;
3724  struct dialed_cc_interfaces *cc_interfaces;
3725  struct cc_recall_ds_data *recall_cc_data;
3726 
3727  ast_channel_lock(chan);
3728  if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
3729  cc_interfaces = cc_datastore->data;
3730  cc_interfaces->ignore = 1;
3731  }
3732 
3733  if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3734  recall_cc_data = cc_recall_datastore->data;
3735  recall_cc_data->ignore = 1;
3736  }
3737  ast_channel_unlock(chan);
3738 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1989
static const struct ast_datastore_info recall_ds_info
Definition: ccss.c:3399
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * data
Definition: datastore.h:70

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

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

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

Referenced by analog_call(), and sip_handle_cc().

4151 {
4152  struct ast_frame frame = {0,};
4153  char device_name[AST_CHANNEL_NAME];
4154  int retval;
4155  struct ast_cc_config_params *cc_params;
4156 
4157  cc_params = ast_channel_get_cc_config_params(chan);
4158  if (!cc_params) {
4159  return -1;
4160  }
4161  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4162  if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
4163  ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
4164  return -1;
4165  }
4166 
4167  if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) {
4168  /* Frame building failed. We can't use this. */
4169  return -1;
4170  }
4171  retval = ast_queue_frame(chan, &frame);
4172  ast_frfree(&frame);
4173  return retval;
4174 }
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:10675
#define ast_log
Definition: astobj2.c:42
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1139
int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char *monitor_type, const char *const device_name, const char *const dialstring, enum ast_cc_service_type service, void *private_data, struct ast_frame *frame)
Create a CC Control frame.
Definition: ccss.c:4176
#define LOG_NOTICE
Definition: logger.h:263
#define AST_CHANNEL_NAME
Definition: channel.h:172
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition: ccss.c:984
static ENTRY retval
Definition: hsearch.c:50
#define ast_frfree(fr)
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:10697
Data structure associated with a single frame of data.
enum ast_cc_service_type service
Definition: ccss.c:383
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:4368

◆ 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
Return values
void

Definition at line 965 of file ccss.c.

References ast_copy_string(), ast_strlen_zero, and ast_cc_config_params::cc_agent_dialstring.

Referenced by ast_cc_set_param().

966 {
967  if (ast_strlen_zero(value)) {
968  config->cc_agent_dialstring[0] = '\0';
969  } else {
971  }
972 }
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char cc_agent_dialstring[AST_MAX_EXTENSION]
Definition: ccss.c:172

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

References AST_CC_AGENT_GENERIC, ast_cc_config_params::cc_agent_policy, and value.

Referenced by ast_cc_set_param(), and build_peer().

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

◆ ast_set_cc_callback_macro()

void ast_set_cc_callback_macro ( struct ast_cc_config_params config,
const char *const  value 
)

Set the callback_macro name.

Since
1.8
Parameters
configThe configuration to set the callback_macro on
valueThe new callback macro we want to change to
Return values
void

Definition at line 1004 of file ccss.c.

References ast_copy_string(), ast_log, ast_strlen_zero, ast_cc_config_params::cc_callback_macro, and LOG_WARNING.

Referenced by ast_cc_set_param().

1005 {
1006  ast_log(LOG_WARNING, "Usage of cc_callback_macro is deprecated. Please use cc_callback_sub instead.\n");
1007  if (ast_strlen_zero(value)) {
1008  config->cc_callback_macro[0] = '\0';
1009  } else {
1010  ast_copy_string(config->cc_callback_macro, value, sizeof(config->cc_callback_macro));
1011  }
1012 }
#define LOG_WARNING
Definition: logger.h:274
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
char cc_callback_macro[AST_MAX_EXTENSION]
Definition: ccss.c:170
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ 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
Return values
void

Definition at line 1014 of file ccss.c.

References ast_copy_string(), ast_strlen_zero, and ast_cc_config_params::cc_callback_sub.

Referenced by ast_cc_set_param().

1015 {
1016  if (ast_strlen_zero(value)) {
1017  config->cc_callback_sub[0] = '\0';
1018  } else {
1019  ast_copy_string(config->cc_callback_sub, value, sizeof(config->cc_callback_sub));
1020  }
1021 }
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
char cc_callback_sub[AST_MAX_EXTENSION]
Definition: ccss.c:171
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

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

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_str_buffer(), ast_str_create, build_cc_interfaces_chanvar(), cc_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(), and str.

Referenced by local_call().

3669 {
3670  struct ast_datastore *recall_datastore;
3671  struct cc_monitor_tree *interface_tree;
3672  struct ast_cc_monitor *monitor_iter;
3673  struct cc_recall_ds_data *recall_data;
3674  struct ast_str *str = ast_str_create(64);
3675  int core_id;
3676 
3677  if (!str) {
3678  return -1;
3679  }
3680 
3681  ast_channel_lock(chan);
3682  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3683  ast_channel_unlock(chan);
3684  ast_free(str);
3685  return -1;
3686  }
3687  recall_data = recall_datastore->data;
3688  interface_tree = recall_data->interface_tree;
3689  core_id = recall_data->core_id;
3690  ast_channel_unlock(chan);
3691 
3692  AST_LIST_LOCK(interface_tree);
3693  AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) {
3694  if (!strcmp(monitor_iter->interface->device_name, extension)) {
3695  break;
3696  }
3697  }
3698 
3699  if (!monitor_iter) {
3700  /* We couldn't find this extension. This may be because
3701  * we have been directed into an unexpected extension because
3702  * the admin has changed a CC_INTERFACES variable at some point.
3703  */
3704  AST_LIST_UNLOCK(interface_tree);
3705  ast_free(str);
3706  return -1;
3707  }
3708 
3709  build_cc_interfaces_chanvar(monitor_iter, &str);
3710  AST_LIST_UNLOCK(interface_tree);
3711 
3712  pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3713  ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3714  core_id, ast_str_buffer(str));
3715 
3716  ast_free(str);
3717  return 0;
3718 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static const struct ast_datastore_info recall_ds_info
Definition: ccss.c:3399
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str **str)
Definition: ccss.c:3588
Structure for a data store object.
Definition: datastore.h:68
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:2404
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
structure to hold extensions
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
The "tree" of interfaces that is dialed.
Definition: ccss.c:324
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
struct ast_cc_interface * interface
Definition: ccss.h:514
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void * data
Definition: datastore.h:70
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3375
char device_name[1]
Definition: ccss.h:839
static int cc_logger_level
Definition: ccss.c:133
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ 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
Return values
void

Definition at line 979 of file ccss.c.

References ast_cc_config_params::cc_max_agents, and value.

Referenced by ast_cc_set_param().

980 {
981  config->cc_max_agents = value;
982 }
int value
Definition: syslog.c:37
unsigned int cc_max_agents
Definition: ccss.c:168

◆ 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
Return values
void

Definition at line 989 of file ccss.c.

References ast_cc_config_params::cc_max_monitors, and value.

Referenced by ast_cc_set_param().

990 {
991  config->cc_max_monitors = value;
992 }
int value
Definition: syslog.c:37
unsigned int cc_max_monitors
Definition: ccss.c:169

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

References AST_CC_MONITOR_ALWAYS, ast_cc_config_params::cc_monitor_policy, and value.

Referenced by ast_cc_set_param().

889 {
890  /* Screw C and its weak type checking for making me have to do this
891  * validation at runtime.
892  */
893  if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) {
894  return -1;
895  }
896  config->cc_monitor_policy = value;
897  return 0;
898 }
int value
Definition: syslog.c:37
enum ast_cc_monitor_policies cc_monitor_policy
Definition: ccss.c:163

◆ 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
Return values
void

Definition at line 905 of file ccss.c.

References ast_log, ast_cc_config_params::cc_offer_timer, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

906 {
907  /* 0 is an unreasonable value for any timer. Stick with the default */
908  if (value == 0) {
909  ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer);
910  return;
911  }
912  config->cc_offer_timer = value;
913 }
#define LOG_WARNING
Definition: logger.h:274
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
unsigned int cc_offer_timer
Definition: ccss.c:164

◆ 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
Return values
void

Definition at line 935 of file ccss.c.

References ast_log, ast_cc_config_params::cc_recall_timer, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

936 {
937  /* 0 is an unreasonable value for any timer. Stick with the default */
938  if (value == 0) {
939  ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->cc_recall_timer);
940  return;
941  }
942  config->cc_recall_timer = value;
943 }
#define LOG_WARNING
Definition: logger.h:274
unsigned int cc_recall_timer
Definition: ccss.c:167
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42

◆ 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
Return values
void

Definition at line 950 of file ccss.c.

References ast_log, ast_cc_config_params::ccbs_available_timer, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

951 {
952  /* 0 is an unreasonable value for any timer. Stick with the default */
953  if (value == 0) {
954  ast_log(LOG_WARNING, "0 is an invalid value for ccbs_available_timer. Retaining value as %u\n", config->ccbs_available_timer);
955  return;
956  }
957  config->ccbs_available_timer = value;
958 }
#define LOG_WARNING
Definition: logger.h:274
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
unsigned int ccbs_available_timer
Definition: ccss.c:166

◆ 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
Return values
void

Definition at line 920 of file ccss.c.

References ast_log, ast_cc_config_params::ccnr_available_timer, LOG_WARNING, and value.

Referenced by ast_cc_set_param().

921 {
922  /* 0 is an unreasonable value for any timer. Stick with the default */
923  if (value == 0) {
924  ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->ccnr_available_timer);
925  return;
926  }
927  config->ccnr_available_timer = value;
928 }
#define LOG_WARNING
Definition: logger.h:274
unsigned int ccnr_available_timer
Definition: ccss.c:165
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42

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

References ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_free, cc_ref(), cc_unref(), 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, and NULL.

Referenced by generic_recall(), and handle_request_invite().

3406 {
3407  struct ast_datastore *recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL);
3408  struct cc_recall_ds_data *recall_data;
3409  struct cc_core_instance *core_instance;
3410 
3411  if (!recall_datastore) {
3412  return -1;
3413  }
3414 
3415  if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) {
3416  ast_datastore_free(recall_datastore);
3417  return -1;
3418  }
3419 
3420  if (!(core_instance = find_cc_core_instance(core_id))) {
3421  ast_free(recall_data);
3422  ast_datastore_free(recall_datastore);
3423  return -1;
3424  }
3425 
3426  recall_data->interface_tree = cc_ref(core_instance->monitors,
3427  "Bump refcount for monitor tree for recall datastore");
3428  recall_data->core_id = core_id;
3429  recall_datastore->data = recall_data;
3430  recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
3431  ast_channel_lock(chan);
3432  ast_channel_datastore_add(chan, recall_datastore);
3433  ast_channel_unlock(chan);
3434  cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref");
3435  return 0;
3436 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
#define ast_channel_lock(chan)
Definition: channel.h:2945
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
static const struct ast_datastore_info recall_ds_info
Definition: ccss.c:3399
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:193
unsigned int inheritance
Definition: datastore.h:73
void * data
Definition: datastore.h:70
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3375
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390

◆ build_cc_interfaces_chanvar()

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

Definition at line 3588 of file ccss.c.

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

Referenced by ast_cc_agent_set_interfaces_chanvar(), and ast_set_cc_interfaces_chanvar().

3589 {
3590  struct extension_monitor_pvt *extension_pvt;
3591  struct extension_child_dialstring *child_dialstring;
3592  struct ast_cc_monitor *monitor_iter = starting_point;
3593  int top_level_id = starting_point->id;
3594  size_t length;
3595 
3596  /* Init to an empty string. */
3597  ast_str_truncate(*str, 0);
3598 
3599  /* First we need to take all of the is_valid child_dialstrings from
3600  * the extension monitor we found and add them to the CC_INTERFACES
3601  * chanvar
3602  */
3603  extension_pvt = starting_point->private_data;
3604  AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
3605  if (child_dialstring->is_valid) {
3606  cc_unique_append(str, child_dialstring->original_dialstring);
3607  }
3608  }
3609 
3610  /* And now we get the dialstrings from each of the device monitors */
3611  while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) {
3612  if (monitor_iter->parent_id == top_level_id) {
3613  cc_unique_append(str, monitor_iter->dialstring);
3614  }
3615  }
3616 
3617  /* str will have an extra '&' tacked onto the end of it, so we need
3618  * to get rid of that.
3619  */
3620  length = ast_str_strlen(*str);
3621  if (length) {
3622  ast_str_truncate(*str, length - 1);
3623  }
3624  if (length <= 1) {
3625  /* Nothing to recall? This should not happen. */
3626  ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n",
3627  starting_point->interface->device_name);
3628  }
3629 }
static void cc_unique_append(struct ast_str **str, const char *dialstring)
Definition: ccss.c:3558
struct ast_cc_monitor * next
Definition: ccss.h:562
unsigned int id
Definition: ccss.h:519
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition: ccss.c:1810
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
unsigned int parent_id
Definition: ccss.h:524
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:738
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
struct extension_monitor_pvt::@366 child_dialstrings
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char * dialstring
Name that should be used to recall specified interface.
Definition: ccss.h:543
struct ast_cc_interface * interface
Definition: ccss.h:514
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
char original_dialstring[AST_CHANNEL_NAME]
the original dialstring used to call a particular device
Definition: ccss.c:1776
Data regarding an extension monitor&#39;s child&#39;s dialstrings.
Definition: ccss.c:1760
Private data for an extension monitor.
Definition: ccss.c:1817
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:561
char device_name[1]
Definition: ccss.h:839

◆ call_destructor_with_no_monitor()

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

Definition at line 2216 of file ccss.c.

References ast_cc_monitor_callbacks::destructor, and find_monitor_callbacks().

Referenced by ast_cc_busy_interface(), and ast_handle_cc_control_frame().

2217 {
2218  const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type);
2219 
2220  if (!monitor_callbacks) {
2221  return;
2222  }
2223 
2224  monitor_callbacks->destructor(private_data);
2225 }
static const struct ast_cc_monitor_callbacks * find_monitor_callbacks(const char *const type)
Definition: ccss.c:1200
void(* destructor)(void *private_data)
Destroy private data on the monitor.
Definition: ccss.h:668
Callbacks defined by CC monitors.
Definition: ccss.h:576

◆ cancel_available_timer()

static void cancel_available_timer ( struct cc_core_instance core_instance)
static

Definition at line 3226 of file ccss.c.

References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, 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().

3227 {
3228  struct ast_cc_monitor *monitor_iter;
3229  AST_LIST_LOCK(core_instance->monitors);
3230  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3231  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3232  if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) {
3234  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3235  monitor_iter->interface->device_name, 1);
3236  cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor");
3237  }
3238  }
3239  }
3241 
3242  if (!has_device_monitors(core_instance)) {
3243  ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers");
3244  }
3245  AST_LIST_UNLOCK(core_instance->monitors);
3246 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
struct ast_cc_monitor * next
Definition: ccss.h:562
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int(* cancel_available_timer)(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
Definition: ccss.h:657
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:2050
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:551
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
unsigned int parent_id
Definition: ccss.h:524
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
struct ast_cc_interface * interface
Definition: ccss.h:514
int available_timer_id
Definition: ccss.h:547
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:3093
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
char device_name[1]
Definition: ccss.h:839
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

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

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

3169 {
3170  /* Either
3171  * 1. Callee accepted CC request, call agent's ack callback.
3172  * 2. Caller became available, call agent's stop_monitoring callback and
3173  * call monitor's unsuspend callback.
3174  */
3175  if (previous_state == CC_CALLER_REQUESTED) {
3176  core_instance->agent->callbacks->respond(core_instance->agent,
3178  cc_publish_requestacknowledged(core_instance->core_id, core_instance->agent->device_name);
3179  } else if (previous_state == CC_CALLER_BUSY) {
3180  cc_publish_callerstopmonitoring(core_instance->core_id, core_instance->agent->device_name);
3181  unsuspend(core_instance);
3182  }
3183  /* Not possible for previous_state to be anything else due to the is_state_change_valid check at the beginning */
3184  return 0;
3185 }
static void unsuspend(struct cc_core_instance *core_instance)
Definition: ccss.c:3146
static void cc_publish_requestacknowledged(int core_id, const char *caller)
Definition: ccss.c:1099
static void cc_publish_callerstopmonitoring(int core_id, const char *caller)
Definition: ccss.c:1110
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition: ccss.h:965
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
char device_name[1]
Definition: ccss.h:875
struct ast_cc_agent * agent
Definition: ccss.c:341

◆ cc_agent_callback_helper()

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

Definition at line 444 of file ccss.c.

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

Referenced by ast_cc_agent_callback().

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

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

References agent_destroy(), ao2_t_alloc, ast_cc_config_params_init, ast_cc_copy_config_params(), ast_channel_get_cc_config_params(), ast_log_dynamic_level, ast_cc_agent::callbacks, cc_generic_agent_destructor(), cc_generic_agent_init(), cc_generic_agent_recall(), cc_generic_agent_respond(), cc_generic_agent_start_monitoring(), cc_generic_agent_start_offer_timer(), cc_generic_agent_status_request(), cc_generic_agent_stop_offer_timer(), cc_generic_agent_stop_ringing(), 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().

2557 {
2558  struct ast_cc_agent *agent;
2559  struct ast_cc_config_params *cc_params;
2560 
2561  if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy,
2562  "Allocating new ast_cc_agent"))) {
2563  return NULL;
2564  }
2565 
2566  agent->core_id = core_id;
2567  strcpy(agent->device_name, caller_name);
2568 
2569  cc_params = ast_channel_get_cc_config_params(caller_chan);
2570  if (!cc_params) {
2571  cc_unref(agent, "Could not get channel config params.");
2572  return NULL;
2573  }
2574  if (!(agent->cc_params = ast_cc_config_params_init())) {
2575  cc_unref(agent, "Could not init agent config params.");
2576  return NULL;
2577  }
2578  ast_cc_copy_config_params(agent->cc_params, cc_params);
2579 
2580  if (!(agent->callbacks = find_agent_callbacks(caller_chan))) {
2581  cc_unref(agent, "Could not find agent callbacks.");
2582  return NULL;
2583  }
2585 
2586  if (agent->callbacks->init(agent, caller_chan)) {
2587  cc_unref(agent, "Agent init callback failed.");
2588  return NULL;
2589  }
2590  ast_log_dynamic_level(cc_logger_level, "Core %u: Created an agent for caller %s\n",
2591  agent->core_id, agent->device_name);
2592  return agent;
2593 }
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:409
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
struct ast_cc_config_params * cc_params
Definition: ccss.h:859
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define NULL
Definition: resample.c:96
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition: ccss.h:135
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:861
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:10675
static void check_callback_sanity(const struct ast_cc_agent_callbacks *callbacks)
Definition: ccss.c:2532
static const struct ast_cc_agent_callbacks * find_agent_callbacks(struct ast_channel *chan)
Definition: ccss.c:1269
unsigned int core_id
Definition: ccss.h:849
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
char device_name[1]
Definition: ccss.h:875
int(* init)(struct ast_cc_agent *agent, struct ast_channel *chan)
CC agent initialization.
Definition: ccss.h:913
static int cc_logger_level
Definition: ccss.c:133
static void agent_destroy(void *data)
Definition: ccss.c:2544

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

References ast_log, and LOG_WARNING.

3058 {
3059  /* This should never happen... */
3060  ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n");
3061  return -1;
3062 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42

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

References ast_cc_copy_config_params(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), cc_control_payload::config_params, ast_datastore::data, cc_control_payload::device_name, dialed_cc_interfaces::dial_parent_id, 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().

4124 {
4125  struct ast_datastore *datastore;
4126  struct dialed_cc_interfaces *cc_interfaces;
4127  int dial_parent_id;
4128 
4129  ast_channel_lock(chan);
4131  if (!datastore) {
4132  ast_channel_unlock(chan);
4133  return -1;
4134  }
4135  cc_interfaces = datastore->data;
4136  dial_parent_id = cc_interfaces->dial_parent_id;
4137  ast_channel_unlock(chan);
4138 
4139  payload->monitor_type = monitor_type;
4140  payload->private_data = private_data;
4141  payload->service = service;
4142  ast_cc_copy_config_params(&payload->config_params, cc_params);
4144  ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
4145  ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring));
4146  return 0;
4147 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
void * private_data
Private data allocated by the callee.
Definition: ccss.c:257
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1989
int parent_interface_id
ID of parent extension.
Definition: ccss.c:284
Structure for a data store object.
Definition: datastore.h:68
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:2404
#define NULL
Definition: resample.c:96
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:861
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:293
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:305
enum ast_cc_service_type service
Service offered by the endpoint.
Definition: ccss.c:266
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * data
Definition: datastore.h:70
struct ast_cc_config_params config_params
Configuration parameters used by this endpoint.
Definition: ccss.c:275
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:240
unsigned int dial_parent_id
Definition: ccss.c:1902
enum ast_cc_service_type service
Definition: ccss.c:383

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

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

3188 {
3189  core_instance->agent->callbacks->callee_available(core_instance->agent);
3190  return 0;
3191 }
int(* callee_available)(struct ast_cc_agent *agent)
Alert the caller that it is time to try recalling.
Definition: ccss.h:1058
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
struct ast_cc_agent * agent
Definition: ccss.c:341

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

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().

3216 {
3217  /* Callee was available, but caller was busy, call agent's begin_monitoring callback
3218  * and call monitor's suspend callback.
3219  */
3220  suspend(core_instance);
3221  core_instance->agent->callbacks->start_monitoring(core_instance->agent);
3222  cc_publish_callerstartmonitoring(core_instance->core_id, core_instance->agent->device_name);
3223  return 0;
3224 }
static void cc_publish_callerstartmonitoring(int core_id, const char *caller)
Definition: ccss.c:1121
int(* start_monitoring)(struct ast_cc_agent *agent)
Begin monitoring a busy device.
Definition: ccss.h:1039
static void suspend(struct cc_core_instance *core_instance)
Definition: ccss.c:3193
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
char device_name[1]
Definition: ccss.h:875
struct ast_cc_agent * agent
Definition: ccss.c:341

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

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.

3065 {
3066  if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) {
3067  ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n",
3068  core_instance->agent->device_name);
3069  return -1;
3070  }
3071  cc_publish_offertimerstart(core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer);
3072  ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n",
3073  core_instance->core_id, core_instance->agent->device_name);
3074  return 0;
3075 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
struct ast_cc_config_params * cc_params
Definition: ccss.h:859
int(* start_offer_timer)(struct ast_cc_agent *agent)
Start the offer timer.
Definition: ccss.h:934
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
static void cc_publish_offertimerstart(int core_id, const char *caller, unsigned int expires)
Definition: ccss.c:1075
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
char device_name[1]
Definition: ccss.h:875
struct ast_cc_agent * agent
Definition: ccss.c:341
static int cc_logger_level
Definition: ccss.c:133
unsigned int cc_offer_timer
Definition: ccss.c:164

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

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

3133 {
3135  ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n");
3136  core_instance->agent->callbacks->respond(core_instance->agent,
3138  ast_cc_failed(core_instance->core_id, "Too many requests in the system");
3139  return -1;
3140  }
3141  core_instance->agent->callbacks->stop_offer_timer(core_instance->agent);
3142  request_cc(core_instance);
3143  return 0;
3144 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
static void request_cc(struct cc_core_instance *core_instance)
Definition: ccss.c:3108
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:2482
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition: ccss.h:965
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
struct ast_cc_agent * agent
Definition: ccss.c:341
int(* stop_offer_timer)(struct ast_cc_agent *agent)
Stop the offer timer.
Definition: ccss.h:947

◆ cc_cli_output_status()

static int cc_cli_output_status ( void *  data)
static

Definition at line 4494 of file ccss.c.

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

Referenced by handle_cc_status().

4495 {
4496  int *cli_fd = data;
4498 
4499  if (!count) {
4500  ast_cli(*cli_fd, "There are currently no active call completion transactions\n");
4501  } else {
4502  ast_cli(*cli_fd, "%d Call completion transactions\n", count);
4503  ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n");
4504  ast_cli(*cli_fd, "----------------------------------------------------------------------------\n");
4505  ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI");
4506  }
4507  ast_free(cli_fd);
4508  return 0;
4509 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1714
#define ast_free(a)
Definition: astmm.h:182
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
static int print_stats_cb(void *obj, void *arg, int flags)
Definition: ccss.c:4481

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

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

Referenced by print_stats_cb().

4462 {
4463  struct ast_cc_monitor *child_monitor_iter = monitor;
4464  if (!monitor) {
4465  return;
4466  }
4467 
4468  ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name);
4469  if (monitor->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
4470  ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered));
4471  }
4472  ast_cli(fd, "\n");
4473 
4474  while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) {
4475  if (child_monitor_iter->parent_id == monitor->id) {
4476  cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id);
4477  }
4478  }
4479 }
static const char * cc_service_to_string(enum ast_cc_service_type service)
Definition: ccss.c:412
struct ast_cc_monitor * next
Definition: ccss.h:562
unsigned int id
Definition: ccss.h:519
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
unsigned int parent_id
Definition: ccss.h:524
static unsigned int monitor
Definition: chan_phone.c:116
struct ast_cc_interface * interface
Definition: ccss.h:514
static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
Definition: ccss.c:4461
char device_name[1]
Definition: ccss.h:839
enum ast_cc_service_type service_offered
Definition: ccss.h:532
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

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

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

3258 {
3259  /* Recall has made progress, call agent and monitor destructor functions
3260  */
3261  cc_publish_recallcomplete(core_instance->core_id, core_instance->agent->device_name);
3262  ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed");
3263  return 0;
3264 }
static void cc_publish_recallcomplete(int core_id, const char *caller)
Definition: ccss.c:1143
#define ao2_t_unlink(container, obj, tag)
Remove an object from a container.
Definition: astobj2.h:1596
char device_name[1]
Definition: ccss.h:875
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
struct ast_cc_agent * agent
Definition: ccss.c:341

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

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_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().

2942 {
2943  char caller[AST_CHANNEL_NAME];
2944  struct cc_core_instance *core_instance;
2945  struct ast_cc_config_params *cc_params;
2946  long agent_count;
2947  int recall_core_id;
2948 
2949  ast_channel_get_device_name(caller_chan, caller, sizeof(caller));
2950  cc_params = ast_channel_get_cc_config_params(caller_chan);
2951  if (!cc_params) {
2952  ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n",
2953  caller);
2954  return NULL;
2955  }
2956  /* First, we need to kill off other pending CC offers from caller. If the caller is going
2957  * to request a CC service, it may only be for the latest call he made.
2958  */
2959  if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
2960  kill_duplicate_offers(caller);
2961  }
2962 
2963  ast_cc_is_recall(caller_chan, &recall_core_id, NULL);
2964  agent_count = count_agents(caller, recall_core_id);
2965  if (agent_count >= ast_get_cc_max_agents(cc_params)) {
2966  ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller);
2967  return NULL;
2968  }
2969 
2970  /* Generic agents can only have a single outstanding CC request per caller. */
2971  if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
2972  ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n");
2973  return NULL;
2974  }
2975 
2976  /* Next, we need to create the core instance for this call */
2977  if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) {
2978  return NULL;
2979  }
2980 
2981  core_instance->core_id = core_id;
2982  if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) {
2983  cc_unref(core_instance, "Couldn't allocate agent, unref core_instance");
2984  return NULL;
2985  }
2986 
2987  core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree");
2988 
2989  ao2_t_link(cc_core_instances, core_instance, "Link core instance into container");
2990 
2991  return core_instance;
2992 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:409
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
#define ao2_t_link(container, obj, tag)
Add an object to a container.
Definition: astobj2.h:1547
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define NULL
Definition: resample.c:96
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:10675
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:3438
#define AST_CHANNEL_NAME
Definition: channel.h:172
static void kill_duplicate_offers(char *caller)
Definition: ccss.c:2515
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:2554
unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
Get the cc_max_agents.
Definition: ccss.c:974
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:866
static void cc_core_instance_destructor(void *data)
Definition: ccss.c:2928
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
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:10697
static long count_agents(const char *const caller, const int core_id_exception)
Definition: ccss.c:2506
struct ast_cc_agent * agent
Definition: ccss.c:341
static int cc_logger_level
Definition: ccss.c:133

◆ cc_core_instance_cmp_fn()

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

Definition at line 423 of file ccss.c.

References CMP_MATCH, CMP_STOP, and cc_core_instance::core_id.

Referenced by load_module().

424 {
425  struct cc_core_instance *core_instance1 = obj;
426  struct cc_core_instance *core_instance2 = arg;
427 
428  return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0;
429 }

◆ cc_core_instance_destructor()

static void cc_core_instance_destructor ( void *  data)
static

Definition at line 2928 of file ccss.c.

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().

2929 {
2930  struct cc_core_instance *core_instance = data;
2931  ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id);
2932  if (core_instance->agent) {
2933  cc_unref(core_instance->agent, "Core instance is done with the agent now");
2934  }
2935  if (core_instance->monitors) {
2936  core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list");
2937  }
2938 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
struct ast_cc_agent * agent
Definition: ccss.c:341
static int cc_logger_level
Definition: ccss.c:133

◆ cc_core_instance_hash_fn()

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

Definition at line 417 of file ccss.c.

References cc_core_instance::core_id.

Referenced by load_module().

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

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

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

Referenced by ast_handle_cc_control_frame().

2251 {
2252  struct ast_cc_interface *cc_interface;
2253  struct ast_cc_monitor *monitor;
2254  size_t device_name_len = strlen(device_name);
2255  int parent_id = cc_data->parent_interface_id;
2256 
2257  if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy,
2258  "Allocating new ast_cc_interface"))) {
2259  return NULL;
2260  }
2261 
2262  if (!(cc_interface->config_params = ast_cc_config_params_init())) {
2263  cc_unref(cc_interface, "Failed to allocate config params, unref interface");
2264  return NULL;
2265  }
2266 
2267  if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
2268  cc_unref(cc_interface, "Failed to allocate monitor, unref interface");
2269  return NULL;
2270  }
2271 
2272  if (!(monitor->dialstring = ast_strdup(dialstring))) {
2273  cc_unref(monitor, "Failed to copy dialable name. Unref monitor");
2274  cc_unref(cc_interface, "Failed to copy dialable name");
2275  return NULL;
2276  }
2277 
2278  if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) {
2279  cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor");
2280  cc_unref(cc_interface, "Failed to find monitor callbacks");
2281  return NULL;
2282  }
2283 
2284  strcpy(cc_interface->device_name, device_name);
2286  monitor->parent_id = parent_id;
2287  monitor->core_id = core_id;
2288  monitor->service_offered = cc_data->service;
2289  monitor->private_data = cc_data->private_data;
2290  cc_interface->monitor_type = cc_data->monitor_type;
2291  cc_interface->monitor_class = AST_CC_DEVICE_MONITOR;
2292  monitor->interface = cc_interface;
2293  monitor->available_timer_id = -1;
2294  ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params);
2295  ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %u and parent %u\n",
2296  monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id);
2297  return monitor;
2298 }
static const struct ast_cc_monitor_callbacks * find_monitor_callbacks(const char *const type)
Definition: ccss.c:1200
void * private_data
Private data allocated by the callee.
Definition: ccss.c:257
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:409
unsigned int id
Definition: ccss.h:519
static int dialed_cc_interface_counter
Definition: ccss.c:1875
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static void cc_interface_destroy(void *data)
Definition: ccss.c:1737
int parent_interface_id
ID of parent extension.
Definition: ccss.c:284
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:551
#define NULL
Definition: resample.c:96
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition: ccss.h:135
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:861
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:755
unsigned int parent_id
Definition: ccss.h:524
int core_id
Definition: ccss.h:528
Structure with information about an outbound interface.
Definition: ccss.h:818
struct ast_cc_config_params * config_params
Definition: ccss.h:834
static void cc_monitor_destroy(void *data)
Definition: ccss.c:1837
static unsigned int monitor
Definition: chan_phone.c:116
enum ast_cc_service_type service
Service offered by the endpoint.
Definition: ccss.c:266
char * dialstring
Name that should be used to recall specified interface.
Definition: ccss.h:543
const char * monitor_type
The type of monitor that should be used for this interface.
Definition: ccss.h:830
struct ast_cc_interface * interface
Definition: ccss.h:514
struct ast_cc_config_params config_params
Configuration parameters used by this endpoint.
Definition: ccss.c:275
int available_timer_id
Definition: ccss.h:547
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:240
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:561
char device_name[1]
Definition: ccss.h:839
static int cc_logger_level
Definition: ccss.c:133
enum ast_cc_service_type service_offered
Definition: ccss.h:532
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

◆ cc_do_state_change()

static int cc_do_state_change ( void *  datap)
static

Definition at line 3285 of file ccss.c.

References cc_core_instance::agent, args, AST_CC_AGENT_RESPONSE_FAILURE_INVALID, ast_free, ast_log_dynamic_level, ast_cc_agent::callbacks, CC_CALLER_REQUESTED, cc_logger_level, cc_state_to_string(), cc_unref(), ccss_notify_device_state_change(), cc_state_change_args::core_id, cc_state_change_args::core_instance, cc_core_instance::current_state, cc_state_change_args::debug, is_state_change_valid(), ast_cc_agent_callbacks::respond, cc_state_change_args::state, and state_change_funcs.

Referenced by cc_request_state_change().

3286 {
3287  struct cc_state_change_args *args = datap;
3288  struct cc_core_instance *core_instance;
3289  enum cc_state previous_state;
3290  int res;
3291 
3292  ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %u requested. Reason: %s\n",
3293  args->core_id, args->state, args->debug);
3294 
3295  core_instance = args->core_instance;
3296 
3297  if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) {
3298  ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n",
3299  args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state));
3300  if (args->state == CC_CALLER_REQUESTED) {
3301  /*
3302  * For out-of-order requests, we need to let the requester know that
3303  * we can't handle the request now.
3304  */
3305  core_instance->agent->callbacks->respond(core_instance->agent,
3307  }
3308  ast_free(args);
3309  cc_unref(core_instance, "Unref core instance from when it was found earlier");
3310  return -1;
3311  }
3312 
3313  /* We can change to the new state now. */
3314  previous_state = core_instance->current_state;
3315  core_instance->current_state = args->state;
3316  res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state);
3317 
3318  /* If state change successful then notify any device state watchers of the change */
3319  if (!res && !strcmp(core_instance->agent->callbacks->type, "generic")) {
3320  ccss_notify_device_state_change(core_instance->agent->device_name, core_instance->current_state);
3321  }
3322 
3323  ast_free(args);
3324  cc_unref(core_instance, "Unref since state change has completed"); /* From ao2_find */
3325  return res;
3326 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
enum cc_state state
Definition: ccss.c:2996
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
const char * args
struct cc_core_instance * core_instance
Definition: ccss.c:2995
static const char * cc_state_to_string(enum cc_state state)
Definition: ccss.c:407
cc_state
The states used in the CCSS core state machine.
Definition: ccss.c:181
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition: ccss.h:965
static int(*const state_change_funcs[])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state)
Definition: ccss.c:3273
enum cc_state current_state
Definition: ccss.c:337
#define ast_free(a)
Definition: astmm.h:182
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:3001
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
static void ccss_notify_device_state_change(const char *device, enum cc_state state)
Definition: ccss.c:641
struct ast_cc_agent * agent
Definition: ccss.c:341
static int cc_logger_level
Definition: ccss.c:133

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

References AST_LIST_TRAVERSE, extension_monitor_pvt::child_dialstrings, extension_child_dialstring::device_name, ast_cc_monitor::id, extension_child_dialstring::is_valid, cc_core_instance::monitors, 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().

2051 {
2052  struct ast_cc_monitor *monitor_iter;
2053  struct extension_monitor_pvt *extension_pvt;
2054  struct extension_child_dialstring *child_dialstring;
2055 
2056  AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
2057  if (monitor_iter->id == parent_id) {
2058  break;
2059  }
2060  }
2061 
2062  if (!monitor_iter) {
2063  return;
2064  }
2065  extension_pvt = monitor_iter->private_data;
2066 
2067  AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
2068  if (!strcmp(child_dialstring->device_name, device_name)) {
2069  child_dialstring->is_valid = is_valid;
2070  break;
2071  }
2072  }
2073 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
unsigned int id
Definition: ccss.h:519
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition: ccss.c:1810
struct extension_child_dialstring * next
Definition: ccss.c:1811
struct extension_monitor_pvt::@366 child_dialstrings
char device_name[AST_CHANNEL_NAME]
The name of the device being dialed.
Definition: ccss.c:1795
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
Data regarding an extension monitor&#39;s child&#39;s dialstrings.
Definition: ccss.c:1760
Private data for an extension monitor.
Definition: ccss.c:1817
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:561

◆ cc_extension_monitor_destructor()

static void cc_extension_monitor_destructor ( void *  private_data)
static

Definition at line 1821 of file ccss.c.

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

Referenced by cc_monitor_destroy().

1822 {
1823  struct extension_monitor_pvt *extension_pvt = private_data;
1824  struct extension_child_dialstring *child_dialstring;
1825 
1826  /* This shouldn't be possible, but I'm paranoid */
1827  if (!extension_pvt) {
1828  return;
1829  }
1830 
1831  while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) {
1832  ast_free(child_dialstring);
1833  }
1834  ast_free(extension_pvt);
1835 }
struct extension_child_dialstring * next
Definition: ccss.c:1811
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
struct extension_monitor_pvt::@366 child_dialstrings
#define ast_free(a)
Definition: astmm.h:182
Data regarding an extension monitor&#39;s child&#39;s dialstrings.
Definition: ccss.c:1760
Private data for an extension monitor.
Definition: ccss.c:1817

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

References ao2_t_alloc, ast_atomic_fetchadd_int(), AST_CC_EXTENSION_MONITOR, ast_log_dynamic_level, AST_MAX_EXTENSION, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_str_strlen(), cc_interface_destroy(), cc_logger_level, cc_monitor_destroy(), cc_unref(), ast_cc_interface::device_name, extension_monitor_pvt_init(), ast_cc_monitor::id, ast_cc_monitor::interface, monitor, 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().

2090 {
2092  struct ast_cc_interface *cc_interface;
2093  struct ast_cc_monitor *monitor;
2094 
2095  ast_str_set(&str, 0, "%s@%s", exten, context);
2096 
2097  if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy,
2098  "Allocating new ast_cc_interface"))) {
2099  return NULL;
2100  }
2101 
2102  if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
2103  cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface");
2104  return NULL;
2105  }
2106 
2107  if (!(monitor->private_data = extension_monitor_pvt_init())) {
2108  cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor");
2109  cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface");
2110  }
2111 
2113  monitor->parent_id = parent_id;
2114  cc_interface->monitor_type = "extension";
2115  cc_interface->monitor_class = AST_CC_EXTENSION_MONITOR;
2116  strcpy(cc_interface->device_name, ast_str_buffer(str));
2117  monitor->interface = cc_interface;
2118  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);
2119  return monitor;
2120 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static struct extension_monitor_pvt * extension_monitor_pvt_init(void)
Definition: ccss.c:1995
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:409
unsigned int id
Definition: ccss.h:519
static int dialed_cc_interface_counter
Definition: ccss.c:1875
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static void cc_interface_destroy(void *data)
Definition: ccss.c:1737
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define ast_str_alloca(init_len)
Definition: strings.h:800
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
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:755
unsigned int parent_id
Definition: ccss.h:524
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:1065
Structure with information about an outbound interface.
Definition: ccss.h:818
#define AST_MAX_EXTENSION
Definition: channel.h:135
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static void cc_monitor_destroy(void *data)
Definition: ccss.c:1837
static unsigned int monitor
Definition: chan_phone.c:116
const char * monitor_type
The type of monitor that should be used for this interface.
Definition: ccss.h:830
struct ast_cc_interface * interface
Definition: ccss.h:514
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:561
char device_name[1]
Definition: ccss.h:839
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int cc_logger_level
Definition: ccss.c:133
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

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

References cc_core_instance::agent, ao2_t_unlink, cc_publish_failure(), cc_core_instance::core_id, cc_state_change_args::debug, and ast_cc_agent::device_name.

3267 {
3268  cc_publish_failure(core_instance->core_id, core_instance->agent->device_name, args->debug);
3269  ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed");
3270  return 0;
3271 }
#define ao2_t_unlink(container, obj, tag)
Remove an object from a container.
Definition: astobj2.h:1596
char device_name[1]
Definition: ccss.h:875
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
struct ast_cc_agent * agent
Definition: ccss.c:341
static void cc_publish_failure(int core_id, const char *caller, const char *reason)
Definition: ccss.c:1154

◆ cc_generic_agent_destructor()

static void cc_generic_agent_destructor ( struct ast_cc_agent agent)
static

Definition at line 2911 of file ccss.c.

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

Referenced by cc_agent_init().

2912 {
2913  struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
2914 
2915  if (!agent_pvt) {
2916  /* The agent constructor probably failed. */
2917  return;
2918  }
2919 
2921  if (agent_pvt->sub) {
2922  agent_pvt->sub = stasis_unsubscribe(agent_pvt->sub);
2923  }
2924 
2925  ast_free(agent_pvt);
2926 }
void * private_data
Definition: ccss.h:871
static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
Definition: ccss.c:2722
struct stasis_subscription * sub
Definition: ccss.c:2628
Structure representing an agent.
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:973
#define ast_free(a)
Definition: astmm.h:182

◆ cc_generic_agent_init()

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

Definition at line 2669 of file ccss.c.

References ast_calloc, AST_CC_AGENT_SKIP_OFFER, ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_macrocontext(), ast_channel_macroexten(), 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, ast_cc_agent::private_data, and S_OR.

Referenced by cc_agent_init().

2670 {
2671  struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
2672 
2673  if (!generic_pvt) {
2674  return -1;
2675  }
2676 
2677  generic_pvt->offer_timer_id = -1;
2678  if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
2679  ast_copy_string(generic_pvt->cid_num, ast_channel_caller(chan)->id.number.str, sizeof(generic_pvt->cid_num));
2680  }
2681  if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
2682  ast_copy_string(generic_pvt->cid_name, ast_channel_caller(chan)->id.name.str, sizeof(generic_pvt->cid_name));
2683  }
2684  ast_copy_string(generic_pvt->exten, S_OR(ast_channel_macroexten(chan), ast_channel_exten(chan)), sizeof(generic_pvt->exten));
2685  ast_copy_string(generic_pvt->context, S_OR(ast_channel_macrocontext(chan), ast_channel_context(chan)), sizeof(generic_pvt->context));
2686  agent->private_data = generic_pvt;
2688  return 0;
2689 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void * private_data
Definition: ccss.h:871
char cid_num[AST_CHANNEL_NAME]
Definition: ccss.c:2642
#define ast_set_flag(p, flag)
Definition: utils.h:70
char context[AST_CHANNEL_NAME]
Definition: ccss.c:2666
char exten[AST_CHANNEL_NAME]
Definition: ccss.c:2658
Number structure.
Definition: app_followme.c:154
const char * ast_channel_exten(const struct ast_channel *chan)
static const char name[]
Definition: cdr_mysql.c:74
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
char cid_name[AST_CHANNEL_NAME]
Definition: ccss.c:2650
const char * ast_channel_context(const struct ast_channel *chan)
const char * ast_channel_macrocontext(const struct ast_channel *chan)
const char * ast_channel_macroexten(const struct ast_channel *chan)

◆ cc_generic_agent_recall()

static int cc_generic_agent_recall ( struct ast_cc_agent agent)
static

Definition at line 2895 of file ccss.c.

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.

Referenced by cc_agent_init().

2896 {
2897  pthread_t clotho;
2898  enum ast_device_state current_state = ast_device_state(agent->device_name);
2899 
2900  if (!cc_generic_is_device_available(current_state)) {
2901  /* We can't try to contact the device right now because he's not available
2902  * Let the core know he's busy.
2903  */
2904  ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name);
2905  return 0;
2906  }
2908  return 0;
2909 }
ast_device_state
Device States.
Definition: devicestate.h:52
static void * generic_recall(void *data)
Definition: ccss.c:2816
#define NULL
Definition: resample.c:96
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:572
unsigned int core_id
Definition: ccss.h:849
char device_name[1]
Definition: ccss.h:875
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1313
int ast_cc_agent_caller_busy(int core_id, const char *debug,...)
Indicate that the caller is busy.
Definition: ccss.c:3809

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

Referenced by cc_agent_init().

2736 {
2737  /* The generic agent doesn't have to do anything special to
2738  * acknowledge a CC request. Just return.
2739  */
2740  return;
2741 }

◆ cc_generic_agent_start_monitoring()

static int cc_generic_agent_start_monitoring ( struct ast_cc_agent agent)
static

Definition at line 2791 of file ccss.c.

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.

Referenced by cc_agent_init().

2792 {
2793  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2794  struct ast_str *str = ast_str_alloca(128);
2795  struct stasis_topic *device_specific_topic;
2796 
2797  ast_assert(generic_pvt->sub == NULL);
2798  ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n",
2799  agent->device_name);
2800 
2801  device_specific_topic = ast_device_state_topic(agent->device_name);
2802  if (!device_specific_topic) {
2803  return -1;
2804  }
2805 
2806  if (!(generic_pvt->sub = stasis_subscribe(device_specific_topic, generic_agent_devstate_cb, agent))) {
2807  return -1;
2808  }
2812  cc_ref(agent, "Ref agent for subscription");
2813  return 0;
2814 }
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
Definition: devicestate.c:683
void * private_data
Definition: ccss.h:871
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
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:1079
#define ast_assert(a)
Definition: utils.h:695
#define ast_str_alloca(init_len)
Definition: strings.h:800
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
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:1065
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_subscription * sub
Definition: ccss.c:2628
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
char device_name[1]
Definition: ccss.h:875
static void generic_agent_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: ccss.c:2761
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:1025
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.

◆ cc_generic_agent_start_offer_timer()

static int cc_generic_agent_start_offer_timer ( struct ast_cc_agent agent)
static

Definition at line 2703 of file ccss.c.

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(), ast_cc_agent::core_id, NULL, offer_timer_expire(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.

Referenced by cc_agent_init().

2704 {
2705  int when;
2706  int sched_id;
2707  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2708 
2710  ast_assert(agent->cc_params != NULL);
2711 
2712  when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
2713  ast_log_dynamic_level(cc_logger_level, "Core %u: About to schedule offer timer expiration for %d ms\n",
2714  agent->core_id, when);
2715  if ((sched_id = ast_sched_add(cc_sched_context, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) {
2716  return -1;
2717  }
2718  generic_pvt->offer_timer_id = sched_id;
2719  return 0;
2720 }
void * private_data
Definition: ccss.h:871
struct ast_cc_config_params * cc_params
Definition: ccss.h:859
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
Scheduler ID holder.
Definition: sched.c:70
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
static struct ast_sched_context * cc_sched_context
Definition: ccss.c:115
static int offer_timer_expire(const void *data)
Definition: ccss.c:2691
unsigned int core_id
Definition: ccss.h:849
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:565
static int cc_logger_level
Definition: ccss.c:133
unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
Get the cc_offer_timer.
Definition: ccss.c:900

◆ cc_generic_agent_status_request()

static int cc_generic_agent_status_request ( struct ast_cc_agent agent)
static

Definition at line 2743 of file ccss.c.

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

Referenced by cc_agent_init().

2744 {
2746  return 0;
2747 }
ast_device_state
Device States.
Definition: devicestate.h:52
int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate)
Response with a caller&#39;s current status.
Definition: ccss.c:4093
unsigned int core_id
Definition: ccss.h:849
char device_name[1]
Definition: ccss.h:875

◆ cc_generic_agent_stop_offer_timer()

static int cc_generic_agent_stop_offer_timer ( struct ast_cc_agent agent)
static

Definition at line 2722 of file ccss.c.

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

Referenced by cc_agent_init(), and cc_generic_agent_destructor().

2723 {
2724  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2725 
2726  if (generic_pvt->offer_timer_id != -1) {
2727  if (!ast_sched_del(cc_sched_context, generic_pvt->offer_timer_id)) {
2728  cc_unref(agent, "Remove scheduler's reference to the agent");
2729  }
2730  generic_pvt->offer_timer_id = -1;
2731  }
2732  return 0;
2733 }
void * private_data
Definition: ccss.h:871
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct ast_sched_context * cc_sched_context
Definition: ccss.c:115
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition: sched.c:610

◆ cc_generic_agent_stop_ringing()

static int cc_generic_agent_stop_ringing ( struct ast_cc_agent agent)
static

Definition at line 2749 of file ccss.c.

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

Referenced by cc_agent_init().

2750 {
2751  struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name));
2752 
2753  if (!recall_chan) {
2754  return 0;
2755  }
2756 
2758  return 0;
2759 }
Main Channel structure associated with a channel.
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1434
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
char device_name[1]
Definition: ccss.h:875

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

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

Referenced by cc_generic_is_device_available().

1652 {
1653  ast_assert(sched_id != NULL);
1654 
1655  if (*sched_id == -1) {
1656  return 0;
1657  }
1658 
1659  ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n",
1660  monitor->core_id, monitor->interface->device_name);
1662  cc_unref(monitor, "Remove scheduler's reference to the monitor");
1663  }
1664  *sched_id = -1;
1665  return 0;
1666 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
Scheduler ID holder.
Definition: sched.c:70
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
static struct ast_sched_context * cc_sched_context
Definition: ccss.c:115
int core_id
Definition: ccss.h:528
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition: sched.c:610
struct ast_cc_interface * interface
Definition: ccss.h:514
char device_name[1]
Definition: ccss.h:839
static int cc_logger_level
Definition: ccss.c:133

◆ cc_generic_monitor_destructor()

static void cc_generic_monitor_destructor ( void *  private_data)
static

Definition at line 1668 of file ccss.c.

References ao2_t_unlink, ast_cc_monitor_callee_available(), ast_free, AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log_dynamic_level, cc_generic_is_device_available(), cc_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_monitor_instance::is_suspended, generic_monitor_instance_list::list, generic_monitor_instance::monitoring, and generic_monitor_instance::next.

Referenced by cc_generic_is_device_available().

1669 {
1670  struct generic_monitor_pvt *gen_mon_pvt = private_data;
1671  struct generic_monitor_instance_list *generic_list;
1672  struct generic_monitor_instance *generic_instance;
1673 
1674  if (!private_data) {
1675  /* If the private data is NULL, that means that the monitor hasn't even
1676  * been created yet, but that the destructor was called. While this sort
1677  * of behavior is useful for native monitors, with a generic one, there is
1678  * nothing in particular to do.
1679  */
1680  return;
1681  }
1682 
1683  ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n",
1684  gen_mon_pvt->core_id, gen_mon_pvt->device_name);
1685 
1686  if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) {
1687  /* If there's no generic list, that means that the monitor is being destroyed
1688  * before we actually got to request CC. Not a biggie. Same in the situation
1689  * below if the list traversal should complete without finding an entry.
1690  */
1691  ast_free((char *)gen_mon_pvt->device_name);
1692  ast_free(gen_mon_pvt);
1693  return;
1694  }
1695 
1696  AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) {
1697  if (generic_instance->core_id == gen_mon_pvt->core_id) {
1699  ast_free(generic_instance);
1700  break;
1701  }
1702  }
1704 
1705  if (AST_LIST_EMPTY(&generic_list->list)) {
1706  /* No more monitors with this device name exist. Time to unlink this
1707  * list from the container
1708  */
1709  ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container");
1710  } else {
1711  /* There are still instances for this particular device. The situation
1712  * may be that we were attempting a CC recall and a failure occurred, perhaps
1713  * on the agent side. If a failure happens here and the device being monitored
1714  * is available, then we need to signal on the first unsuspended instance that
1715  * the device is available for recall.
1716  */
1717 
1718  /* First things first. We don't even want to consider this action if
1719  * the device in question isn't available right now.
1720  */
1721  if (generic_list->fit_for_recall
1722  && cc_generic_is_device_available(generic_list->current_state)) {
1723  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1724  if (!generic_instance->is_suspended && generic_instance->monitoring) {
1725  ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor "
1726  "availability due to other instance's failure.");
1727  break;
1728  }
1729  }
1730  }
1731  }
1732  cc_unref(generic_list, "Done with generic list in generic monitor destructor");
1733  ast_free((char *)gen_mon_pvt->device_name);
1734  ast_free(gen_mon_pvt);
1735 }
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:3798
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define ao2_t_unlink(container, obj, tag)
Remove an object from a container.
Definition: astobj2.h:1596
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
struct generic_monitor_instance_list::@364 list
struct ao2_container * generic_monitors
Definition: ccss.c:1333
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1386
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:182
private data for generic device monitor
Definition: ccss.c:1368
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1313
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
const char * device_name
Definition: ccss.c:1373
static int cc_logger_level
Definition: ccss.c:133
enum ast_device_state current_state
Definition: ccss.c:1344
struct generic_monitor_instance * next
Definition: ccss.c:1339

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

References ast_calloc, ast_cc_available_timer_expire(), AST_CC_CCBS, AST_CC_CCNL, AST_CC_CCNR, ast_cc_monitor_request_acked(), ast_free, ast_get_ccbs_available_timer(), ast_get_ccnr_available_timer(), AST_LIST_INSERT_TAIL, ast_sched_add(), ast_strdup, cc_ref(), 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.

Referenced by cc_generic_is_device_available().

1520 {
1521  struct generic_monitor_instance_list *generic_list;
1522  struct generic_monitor_instance *generic_instance;
1523  struct generic_monitor_pvt *gen_mon_pvt;
1525  int when;
1526 
1527  /* First things first. Native channel drivers will have their private data allocated
1528  * at the time that they tell the core that they can offer CC. Generic is quite a bit
1529  * different, and we wait until this point to allocate our private data.
1530  */
1531  if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) {
1532  return -1;
1533  }
1534 
1535  if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) {
1536  ast_free(gen_mon_pvt);
1537  return -1;
1538  }
1539 
1540  gen_mon_pvt->core_id = monitor->core_id;
1541 
1542  monitor->private_data = gen_mon_pvt;
1543 
1544  if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1545  if (!(generic_list = create_new_generic_list(monitor))) {
1546  return -1;
1547  }
1548  }
1549 
1550  if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) {
1551  /* The generic monitor destructor will take care of the appropriate
1552  * deallocations
1553  */
1554  cc_unref(generic_list, "Generic monitor instance failed to allocate");
1555  return -1;
1556  }
1557  generic_instance->core_id = monitor->core_id;
1558  generic_instance->monitoring = 1;
1559  AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next);
1560  when = service == AST_CC_CCBS ? ast_get_ccbs_available_timer(monitor->interface->config_params) :
1561  ast_get_ccnr_available_timer(monitor->interface->config_params);
1562 
1563  *available_timer_id = ast_sched_add(cc_sched_context, when * 1000,
1564  ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference"));
1565  if (*available_timer_id == -1) {
1566  cc_unref(monitor, "Failed to schedule available timer. (monitor)");
1567  cc_unref(generic_list, "Failed to schedule available timer. (generic_list)");
1568  return -1;
1569  }
1570  /* If the new instance was created as CCNR, then that means this device is not currently
1571  * fit for recall even if it previously was.
1572  */
1573  if (service == AST_CC_CCNR || service == AST_CC_CCNL) {
1574  generic_list->fit_for_recall = 0;
1575  }
1576  ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.",
1577  monitor->interface->device_name);
1578  cc_unref(generic_list, "Finished with monitor instance reference in request cc callback");
1579  return 0;
1580 }
unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
Get the ccnr_available_timer.
Definition: ccss.c:915
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
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:3787
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
ast_cc_service_type
Definition: ccss.h:32
static struct ast_sched_context * cc_sched_context
Definition: ccss.c:115
int core_id
Definition: ccss.h:528
int ast_cc_available_timer_expire(const void *data)
Scheduler callback for available timer expiration.
Definition: ccss.c:1509
static struct generic_monitor_instance_list * create_new_generic_list(struct ast_cc_monitor *monitor)
Definition: ccss.c:1409
struct generic_monitor_instance_list::@364 list
struct ast_cc_config_params * config_params
Definition: ccss.h:834
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1386
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_cc_interface * interface
Definition: ccss.h:514
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:565
private data for generic device monitor
Definition: ccss.c:1368
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:561
char device_name[1]
Definition: ccss.h:839
const char * device_name
Definition: ccss.c:1373
enum ast_cc_service_type service_offered
Definition: ccss.h:532
enum ast_cc_service_type service
Definition: ccss.c:383
unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
Get the ccbs_available_timer.
Definition: ccss.c:945

◆ cc_generic_monitor_suspend()

static int cc_generic_monitor_suspend ( struct ast_cc_monitor monitor)
static

Definition at line 1582 of file ccss.c.

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.

Referenced by cc_generic_is_device_available().

1583 {
1584  struct generic_monitor_instance_list *generic_list;
1585  struct generic_monitor_instance *generic_instance;
1587 
1588  if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1589  return -1;
1590  }
1591 
1592  /* First we need to mark this particular monitor as being suspended. */
1593  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1594  if (generic_instance->core_id == monitor->core_id) {
1595  generic_instance->is_suspended = 1;
1596  break;
1597  }
1598  }
1599 
1600  /* If the device being suspended is currently in use, then we don't need to
1601  * take any further actions
1602  */
1603  if (!cc_generic_is_device_available(state)) {
1604  cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list.");
1605  return 0;
1606  }
1607 
1608  /* If the device is not in use, though, then it may be possible to report the
1609  * device's availability using a different monitor which is monitoring the
1610  * same device
1611  */
1612 
1613  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1614  if (!generic_instance->is_suspended) {
1615  ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1616  break;
1617  }
1618  }
1619  cc_unref(generic_list, "Done with generic list in suspend callback");
1620  return 0;
1621 }
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:3798
ast_device_state
Device States.
Definition: devicestate.h:52
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
int core_id
Definition: ccss.h:528
struct generic_monitor_instance_list::@364 list
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1386
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_cc_interface * interface
Definition: ccss.h:514
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1313
char device_name[1]
Definition: ccss.h:839
struct generic_monitor_instance * next
Definition: ccss.c:1339

◆ cc_generic_monitor_unsuspend()

static int cc_generic_monitor_unsuspend ( struct ast_cc_monitor monitor)
static

Definition at line 1623 of file ccss.c.

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.

Referenced by cc_generic_is_device_available().

1624 {
1625  struct generic_monitor_instance *generic_instance;
1628 
1629  if (!generic_list) {
1630  return -1;
1631  }
1632  /* If the device is currently available, we can immediately announce
1633  * its availability
1634  */
1635  if (cc_generic_is_device_available(state)) {
1636  ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available");
1637  }
1638 
1639  /* In addition, we need to mark this generic_monitor_instance as not being suspended anymore */
1640  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1641  if (generic_instance->core_id == monitor->core_id) {
1642  generic_instance->is_suspended = 0;
1643  generic_instance->monitoring = 1;
1644  break;
1645  }
1646  }
1647  cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend");
1648  return 0;
1649 }
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:3798
ast_device_state
Device States.
Definition: devicestate.h:52
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
int core_id
Definition: ccss.h:528
struct generic_monitor_instance_list::@364 list
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1386
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_cc_interface * interface
Definition: ccss.h:514
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1313
char device_name[1]
Definition: ccss.h:839

◆ cc_interface_destroy()

static void cc_interface_destroy ( void *  data)
static

Definition at line 1737 of file ccss.c.

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().

1738 {
1739  struct ast_cc_interface *interface = data;
1740  ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name);
1741  ast_cc_config_params_destroy(interface->config_params);
1742 }
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:693
Structure with information about an outbound interface.
Definition: ccss.h:818
static int cc_logger_level
Definition: ccss.c:133

◆ cc_interface_tree_destroy()

static void cc_interface_tree_destroy ( void *  data)
static

Definition at line 1858 of file ccss.c.

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(), monitor, and ast_cc_monitor::next.

Referenced by cc_interfaces_datastore_init().

1859 {
1860  struct cc_monitor_tree *cc_interface_tree = data;
1861  struct ast_cc_monitor *monitor;
1862  while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
1863  if (monitor->callbacks) {
1864  monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id);
1865  }
1866  cc_unref(monitor, "Destroying all monitors");
1867  }
1868  AST_LIST_HEAD_DESTROY(cc_interface_tree);
1869 }
struct ast_cc_monitor * next
Definition: ccss.h:562
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
int(* cancel_available_timer)(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
Definition: ccss.h:657
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:551
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:652
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
static unsigned int monitor
Definition: chan_phone.c:116
The "tree" of interfaces that is dialed.
Definition: ccss.c:324
int available_timer_id
Definition: ccss.h:547

◆ cc_interfaces_datastore_init()

static int cc_interfaces_datastore_init ( struct ast_channel chan)
static

Definition at line 2138 of file ccss.c.

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_macrocontext(), ast_channel_macroexten(), 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, dialed_cc_interfaces::core_id, core_id_counter, ast_datastore::data, DATASTORE_INHERIT_FOREVER, dialed_cc_interfaces::dial_parent_id, ast_cc_monitor::id, ast_datastore::inheritance, dialed_cc_interfaces::interface_tree, interfaces, dialed_cc_interfaces::is_original_caller, monitor, ast_datastore::next, NULL, and S_OR.

Referenced by ast_cc_call_init().

2138  {
2140  struct ast_cc_monitor *monitor;
2141  struct ast_datastore *dial_cc_datastore;
2142 
2143  /*XXX This may be a bit controversial. In an attempt to not allocate
2144  * extra resources, I make sure that a future request will be within
2145  * limits. The problem here is that it is reasonable to think that
2146  * even if we're not within the limits at this point, we may be by
2147  * the time the requestor will have made his request. This may be
2148  * deleted at some point.
2149  */
2151  return 0;
2152  }
2153 
2154  if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) {
2155  return -1;
2156  }
2157 
2159  ast_free(interfaces);
2160  return -1;
2161  }
2162 
2163  if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) {
2164  cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor");
2165  ast_free(interfaces);
2166  return -1;
2167  }
2168 
2169  if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy,
2170  "Allocate monitor tree"))) {
2171  ast_datastore_free(dial_cc_datastore);
2172  cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor");
2173  ast_free(interfaces);
2174  return -1;
2175  }
2176 
2177  /* Finally, all that allocation is done... */
2178  AST_LIST_HEAD_INIT(interfaces->interface_tree);
2179  AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
2180  cc_ref(monitor, "List's reference to extension monitor");
2181  dial_cc_datastore->data = interfaces;
2182  dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
2183  interfaces->dial_parent_id = monitor->id;
2184  interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1);
2185  interfaces->is_original_caller = 1;
2186  ast_channel_lock(chan);
2187  ast_channel_datastore_add(chan, dial_cc_datastore);
2188  ast_channel_unlock(chan);
2189  cc_unref(monitor, "Unreffing allocation's reference");
2190  return 0;
2191 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
struct ast_datastore * next
Definition: datastore.h:74
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:409
unsigned int id
Definition: ccss.h:519
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
static const struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1989
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:2089
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
static int core_id_counter
Definition: ccss.c:120
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:755
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
static struct ao2_container * interfaces
Container for registered format interfaces.
Definition: format.c:65
static void cc_interface_tree_destroy(void *data)
Definition: ccss.c:1858
int core_id
Definition: ccss.h:528
char is_original_caller
Definition: ccss.c:1925
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:2482
const char * ast_channel_exten(const struct ast_channel *chan)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static unsigned int monitor
Definition: chan_phone.c:116
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:625
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:193
unsigned int inheritance
Definition: datastore.h:73
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1929
void * data
Definition: datastore.h:70
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_context(const struct ast_channel *chan)
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
unsigned int dial_parent_id
Definition: ccss.c:1902
const char * ast_channel_macrocontext(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
const char * ast_channel_macroexten(const struct ast_channel *chan)

◆ cc_monitor_destroy()

static void cc_monitor_destroy ( void *  data)
static

Definition at line 1837 of file ccss.c.

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().

1838 {
1839  struct ast_cc_monitor *monitor = data;
1840  /* During the monitor creation process, it is possible for this
1841  * function to be called prior to when callbacks are assigned
1842  * to the monitor. Also, extension monitors do not have callbacks
1843  * assigned to them, so we wouldn't want to segfault when we try
1844  * to destroy one of them.
1845  */
1846  ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n",
1847  monitor->core_id, monitor->interface->device_name);
1850  }
1851  if (monitor->callbacks) {
1852  monitor->callbacks->destructor(monitor->private_data);
1853  }
1854  cc_unref(monitor->interface, "Unreffing tree's reference to interface");
1855  ast_free(monitor->dialstring);
1856 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
void(* destructor)(void *private_data)
Destroy private data on the monitor.
Definition: ccss.h:668
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
static void cc_extension_monitor_destructor(void *private_data)
Definition: ccss.c:1821
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:551
int core_id
Definition: ccss.h:528
static unsigned int monitor
Definition: chan_phone.c:116
#define ast_free(a)
Definition: astmm.h:182
char * dialstring
Name that should be used to recall specified interface.
Definition: ccss.h:543
struct ast_cc_interface * interface
Definition: ccss.h:514
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:561
char device_name[1]
Definition: ccss.h:839
static int cc_logger_level
Definition: ccss.c:133
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

◆ cc_monitor_failed()

static int cc_monitor_failed ( void *  data)
static

Definition at line 3896 of file ccss.c.

References AST_CC_DEVICE_MONITOR, ast_cc_failed(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log_dynamic_level, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, ast_cc_monitor_callbacks::cancel_available_timer, cc_extension_monitor_change_is_valid(), cc_logger_level, cc_publish_monitorfailed(), cc_unref(), cc_core_instance::core_id, ast_cc_monitor::core_id, ast_cc_monitor_failure_data::core_id, ast_cc_monitor_failure_data::debug, ast_cc_interface::device_name, ast_cc_monitor_failure_data::device_name, 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().

3897 {
3898  struct ast_cc_monitor_failure_data *failure_data = data;
3899  struct cc_core_instance *core_instance;
3900  struct ast_cc_monitor *monitor_iter;
3901 
3902  core_instance = find_cc_core_instance(failure_data->core_id);
3903  if (!core_instance) {
3904  /* Core instance no longer exists or invalid core_id. */
3906  "Core %d: Could not find core instance for device %s '%s'\n",
3907  failure_data->core_id, failure_data->device_name, failure_data->debug);
3908  ast_free((char *) failure_data->device_name);
3909  ast_free((char *) failure_data->debug);
3910  ast_free(failure_data);
3911  return -1;
3912  }
3913 
3914  AST_LIST_LOCK(core_instance->monitors);
3915  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3916  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3917  if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) {
3919  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3920  monitor_iter->interface->device_name, 1);
3921  monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id);
3922  cc_publish_monitorfailed(monitor_iter->core_id, monitor_iter->interface->device_name);
3923  cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference.");
3924  }
3925  }
3926  }
3928 
3929  if (!has_device_monitors(core_instance)) {
3930  ast_cc_failed(core_instance->core_id, "All monitors have failed\n");
3931  }
3932  AST_LIST_UNLOCK(core_instance->monitors);
3933  cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n");
3934 
3935  ast_free((char *) failure_data->device_name);
3936  ast_free((char *) failure_data->debug);
3937  ast_free(failure_data);
3938  return 0;
3939 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
struct ast_cc_monitor * next
Definition: ccss.h:562
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int(* cancel_available_timer)(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
Definition: ccss.h:657
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
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:2050
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:551
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
unsigned int parent_id
Definition: ccss.h:524
const char * device_name
Definition: ccss.c:3891
int core_id
Definition: ccss.h:528
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
static void cc_publish_monitorfailed(int core_id, const char *callee)
Definition: ccss.c:1166
#define ast_free(a)
Definition: astmm.h:182
struct ast_cc_interface * interface
Definition: ccss.h:514
int available_timer_id
Definition: ccss.h:547
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:3093
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
char device_name[1]
Definition: ccss.h:839
static int cc_logger_level
Definition: ccss.c:133
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

◆ cc_offer()

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

Definition at line 3740 of file ccss.c.

References CC_CALLER_OFFERED, and cc_request_state_change().

Referenced by ast_cc_offer().

3741 {
3742  va_list ap;
3743  int res;
3744 
3745  va_start(ap, debug);
3747  va_end(ap);
3748  return res;
3749 }
static int debug
Global debug status.
Definition: res_xmpp.c:435
int core_id
Definition: ccss.h:528
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3328

◆ cc_party_b_free()

static int cc_party_b_free ( void *  data)
static

Definition at line 4039 of file ccss.c.

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

Referenced by ast_cc_monitor_party_b_free().

4040 {
4041  struct cc_core_instance *core_instance = data;
4042  int res = 0;
4043 
4044  if (core_instance->agent->callbacks->party_b_free) {
4045  res = core_instance->agent->callbacks->party_b_free(core_instance->agent);
4046  }
4047  cc_unref(core_instance, "Party B free finished. Unref core_instance");
4048  return res;
4049 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
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:1023
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
struct ast_cc_agent * agent
Definition: ccss.c:341

◆ cc_publish()

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

Definition at line 1023 of file ccss.c.

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().

1024 {
1025  struct ast_json *blob;
1026  struct ast_json_payload *payload;
1027  struct stasis_message *message;
1028 
1029  if (!message_type) {
1030  return -1;
1031  }
1032 
1033  blob = ast_json_pack("{s: i}",
1034  "core_id", core_id);
1035  if (!blob) {
1036  return -1;
1037  }
1038 
1039  if (extras) {
1040  ast_json_object_update(blob, extras);
1041  }
1042 
1043  payload = ast_json_payload_create(blob);
1044  ast_json_unref(blob);
1045 
1046  if (!payload) {
1047  return -1;
1048  }
1049 
1050  message = stasis_message_create(message_type, payload);
1051  ao2_ref(payload, -1);
1052 
1053  if (!message) {
1054  return -1;
1055  }
1056 
1057  stasis_publish(ast_system_topic(), message);
1058  ao2_ref(message, -1);
1059 
1060  return 0;
1061 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
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:735
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
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:416
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
struct stasis_topic * ast_system_topic(void)
A Stasis Message Bus API topic which publishes messages regarding system changes. ...
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
Abstract JSON element (object, array, string, int, ...).

◆ cc_publish_available()

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

Definition at line 1063 of file ccss.c.

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

Referenced by ast_handle_cc_control_frame().

1064 {
1065  struct ast_json *extras;
1066 
1067  extras = ast_json_pack("{s: s, s: s}",
1068  "callee", callee,
1069  "service", service);
1070 
1071  cc_publish(ast_cc_available_type(), core_id, extras);
1072  ast_json_unref(extras);
1073 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct stasis_message_type * ast_cc_available_type(void)
A stasis_message_type for CCSS Available messages.
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023
enum ast_cc_service_type service
Definition: ccss.c:383

◆ cc_publish_callerrecalling()

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

Definition at line 1132 of file ccss.c.

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

Referenced by cc_recalling().

1133 {
1134  struct ast_json *extras;
1135 
1136  extras = ast_json_pack("{s: s}",
1137  "caller", caller);
1138 
1139  cc_publish(ast_cc_callerrecalling_type(), core_id, extras);
1140  ast_json_unref(extras);
1141 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct stasis_message_type * ast_cc_callerrecalling_type(void)
A stasis_message_type for CCSS Caller Recalling messages.
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023

◆ cc_publish_callerstartmonitoring()

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

Definition at line 1121 of file ccss.c.

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

Referenced by cc_caller_busy().

1122 {
1123  struct ast_json *extras;
1124 
1125  extras = ast_json_pack("{s: s}",
1126  "caller", caller);
1127 
1128  cc_publish(ast_cc_callerstartmonitoring_type(), core_id, extras);
1129  ast_json_unref(extras);
1130 }
struct stasis_message_type * ast_cc_callerstartmonitoring_type(void)
A stasis_message_type for CCSS Caller Start Monitoring messages.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023

◆ cc_publish_callerstopmonitoring()

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

Definition at line 1110 of file ccss.c.

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

Referenced by cc_active().

1111 {
1112  struct ast_json *extras;
1113 
1114  extras = ast_json_pack("{s: s}",
1115  "caller", caller);
1116 
1117  cc_publish(ast_cc_callerstopmonitoring_type(), core_id, extras);
1118  ast_json_unref(extras);
1119 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct stasis_message_type * ast_cc_callerstopmonitoring_type(void)
A stasis_message_type for CCSS Caller Stop Monitoring messages.
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023

◆ cc_publish_failure()

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

Definition at line 1154 of file ccss.c.

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

Referenced by cc_failed().

1155 {
1156  struct ast_json *extras;
1157 
1158  extras = ast_json_pack("{s: s, s: s}",
1159  "caller", caller,
1160  "reason", reason);
1161 
1162  cc_publish(ast_cc_failure_type(), core_id, extras);
1163  ast_json_unref(extras);
1164 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct stasis_message_type * ast_cc_failure_type(void)
A stasis_message_type for CCSS Failure messages.
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023

◆ cc_publish_monitorfailed()

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

Definition at line 1166 of file ccss.c.

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

Referenced by cc_monitor_failed().

1167 {
1168  struct ast_json *extras;
1169 
1170  extras = ast_json_pack("{s: s}",
1171  "callee", callee);
1172 
1173  cc_publish(ast_cc_monitorfailed_type(), core_id, extras);
1174  ast_json_unref(extras);
1175 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct stasis_message_type * ast_cc_monitorfailed_type(void)
A stasis_message_type for CCSS Monitor Failed messages.
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023

◆ cc_publish_offertimerstart()

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

Definition at line 1075 of file ccss.c.

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

Referenced by cc_caller_offered().

1076 {
1077  struct ast_json *extras;
1078 
1079  extras = ast_json_pack("{s: s, s: I}",
1080  "caller", caller,
1081  "expires", (ast_json_int_t)expires);
1082 
1083  cc_publish(ast_cc_offertimerstart_type(), core_id, extras);
1084  ast_json_unref(extras);
1085 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
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.
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023

◆ cc_publish_recallcomplete()

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

Definition at line 1143 of file ccss.c.

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

Referenced by cc_complete().

1144 {
1145  struct ast_json *extras;
1146 
1147  extras = ast_json_pack("{s: s}",
1148  "caller", caller);
1149 
1150  cc_publish(ast_cc_recallcomplete_type(), core_id, extras);
1151  ast_json_unref(extras);
1152 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct stasis_message_type * ast_cc_recallcomplete_type(void)
A stasis_message_type for CCSS Recall Complete messages.
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023

◆ cc_publish_requestacknowledged()

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

Definition at line 1099 of file ccss.c.

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

Referenced by cc_active().

1100 {
1101  struct ast_json *extras;
1102 
1103  extras = ast_json_pack("{s: s}",
1104  "caller", caller);
1105 
1106  cc_publish(ast_cc_requestacknowledged_type(), core_id, extras);
1107  ast_json_unref(extras);
1108 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct stasis_message_type * ast_cc_requestacknowledged_type(void)
A stasis_message_type for CCSS Request Acknowledged messages.
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023

◆ cc_publish_requested()

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

Definition at line 1087 of file ccss.c.

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

Referenced by request_cc().

1088 {
1089  struct ast_json *extras;
1090 
1091  extras = ast_json_pack("{s: s, s: s}",
1092  "caller", caller,
1093  "callee", callee);
1094 
1095  cc_publish(ast_cc_requested_type(), core_id, extras);
1096  ast_json_unref(extras);
1097 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct stasis_message_type * ast_cc_requested_type(void)
A stasis_message_type for CCSS Requested messages.
Abstract JSON element (object, array, string, int, ...).
static int cc_publish(struct stasis_message_type *message_type, int core_id, struct ast_json *extras)
Definition: ccss.c:1023

◆ cc_recall_ds_destroy()

static void cc_recall_ds_destroy ( void *  data)
static

Definition at line 3392 of file ccss.c.

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

3393 {
3394  struct cc_recall_ds_data *recall_data = data;
3395  recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree");
3396  ast_free(recall_data);
3397 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define ast_free(a)
Definition: astmm.h:182
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3375

◆ cc_recall_ds_duplicate()

static void* cc_recall_ds_duplicate ( void *  data)
static

Definition at line 3378 of file ccss.c.

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

3379 {
3380  struct cc_recall_ds_data *old_data = data;
3381  struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data));
3382 
3383  if (!new_data) {
3384  return NULL;
3385  }
3386  new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate");
3387  new_data->core_id = old_data->core_id;
3388  new_data->nested = 1;
3389  return new_data;
3390 }
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
#define NULL
Definition: resample.c:96
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3375

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

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

3249 {
3250  /* Both caller and callee are available, call agent's recall callback
3251  */
3252  cancel_available_timer(core_instance);
3253  cc_publish_callerrecalling(core_instance->core_id, core_instance->agent->device_name);
3254  return 0;
3255 }
static void cc_publish_callerrecalling(int core_id, const char *caller)
Definition: ccss.c:1132
static void cancel_available_timer(struct cc_core_instance *core_instance)
Definition: ccss.c:3226
char device_name[1]
Definition: ccss.h:875
struct ast_cc_agent * agent
Definition: ccss.c:341

◆ cc_ref()

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

Definition at line 143 of file ccss.c.

References ao2_t_ref.

Referenced by ast_cc_agent_callback(), ast_cc_call_init(), ast_cc_get_monitor_by_recall_core_id(), ast_handle_cc_control_frame(), ast_setup_cc_recall_datastore(), cc_core_init_instance(), cc_generic_agent_start_monitoring(), cc_generic_agent_start_offer_timer(), cc_generic_monitor_request_cc(), cc_interfaces_datastore_init(), cc_recall_ds_duplicate(), and dialed_cc_interfaces_duplicate().

144 {
145  ao2_t_ref(obj, +1, debug);
146  return obj;
147 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
static int debug
Global debug status.
Definition: res_xmpp.c:435

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

References args, ast_calloc, ast_free, ast_log_dynamic_level, ast_taskprocessor_push(), cc_do_state_change(), cc_logger_level, cc_unref(), cc_state_change_args::core_id, cc_state_change_args::core_instance, cc_state_change_args::debug, dummy(), find_cc_core_instance(), state, and cc_state_change_args::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().

3329 {
3330  int res;
3331  int debuglen;
3332  char dummy[1];
3333  va_list aq;
3334  struct cc_core_instance *core_instance;
3335  struct cc_state_change_args *args;
3336  /* This initial call to vsnprintf is simply to find what the
3337  * size of the string needs to be
3338  */
3339  va_copy(aq, ap);
3340  /* We add 1 to the result since vsnprintf's return does not
3341  * include the terminating null byte
3342  */
3343  debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1;
3344  va_end(aq);
3345 
3346  if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) {
3347  return -1;
3348  }
3349 
3350  core_instance = find_cc_core_instance(core_id);
3351  if (!core_instance) {
3352  ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n",
3353  core_id);
3354  ast_free(args);
3355  return -1;
3356  }
3357 
3358  args->core_instance = core_instance;
3359  args->state = state;
3360  args->core_id = core_id;
3361  vsnprintf(args->debug, debuglen, debug, ap);
3362 
3364  if (res) {
3365  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3366  ast_free(args);
3367  }
3368  return res;
3369 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:431
enum cc_state state
Definition: ccss.c:393
static int debug
Global debug status.
Definition: res_xmpp.c:435
static void dummy(char *unused,...)
Definition: chan_unistim.c:220
enum cc_state state
Definition: ccss.c:2996
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
const char * args
struct cc_core_instance * core_instance
Definition: ccss.c:2995
static int cc_do_state_change(void *datap)
Definition: ccss.c:3285
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static int cc_logger_level
Definition: ccss.c:133
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

◆ cc_service_to_string()

static const char* cc_service_to_string ( enum ast_cc_service_type  service)
static

Definition at line 412 of file ccss.c.

References cc_service_to_string_map, and service.

Referenced by ast_handle_cc_control_frame(), and cc_cli_print_monitor_stats().

413 {
414  return cc_service_to_string_map[service].service_string;
415 }
static const struct @359 cc_service_to_string_map[]
enum ast_cc_service_type service
Definition: ccss.c:383

◆ cc_state_to_devstate()

static enum ast_device_state cc_state_to_devstate ( enum cc_state  state)
static

Definition at line 584 of file ccss.c.

References state.

Referenced by ccss_device_state(), and ccss_notify_device_state_change().

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

◆ cc_state_to_string()

static const char* cc_state_to_string ( enum cc_state  state)
static

Definition at line 407 of file ccss.c.

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().

408 {
409  return cc_state_to_string_map[state].state_string;
410 }
static const struct @360 cc_state_to_string_map[]
enum cc_state state
Definition: ccss.c:393

◆ cc_status_request()

static int cc_status_request ( void *  data)
static

Definition at line 3976 of file ccss.c.

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

Referenced by ast_cc_monitor_status_request().

3977 {
3978  struct cc_core_instance *core_instance= data;
3979  int res;
3980 
3981  res = core_instance->agent->callbacks->status_request(core_instance->agent);
3982  cc_unref(core_instance, "Status request finished. Unref core instance");
3983  return res;
3984 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
int(* status_request)(struct ast_cc_agent *agent)
Request the status of the agent&#39;s device.
Definition: ccss.h:980
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
struct ast_cc_agent * agent
Definition: ccss.c:341

◆ cc_status_response()

static int cc_status_response ( void *  data)
static

Definition at line 4072 of file ccss.c.

References args, AST_CC_DEVICE_MONITOR, ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_unref(), cc_status_response_args::core_instance, cc_status_response_args::devstate, 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().

4073 {
4074  struct cc_status_response_args *args = data;
4075  struct cc_core_instance *core_instance = args->core_instance;
4076  struct ast_cc_monitor *monitor_iter;
4077  enum ast_device_state devstate = args->devstate;
4078 
4079  ast_free(args);
4080 
4081  AST_LIST_LOCK(core_instance->monitors);
4082  AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
4083  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR &&
4084  monitor_iter->callbacks->status_response) {
4085  monitor_iter->callbacks->status_response(monitor_iter, devstate);
4086  }
4087  }
4088  AST_LIST_UNLOCK(core_instance->monitors);
4089  cc_unref(core_instance, "Status response finished. Unref core instance");
4090  return 0;
4091 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
struct ast_cc_monitor * next
Definition: ccss.h:562
ast_device_state
Device States.
Definition: devicestate.h:52
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:551
const char * args
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:628
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct cc_core_instance * core_instance
Definition: ccss.c:4068
#define ast_free(a)
Definition: astmm.h:182
struct ast_cc_interface * interface
Definition: ccss.h:514
enum ast_device_state devstate
Definition: ccss.c:4069
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

◆ cc_stop_ringing()

static int cc_stop_ringing ( void *  data)
static

Definition at line 4002 of file ccss.c.

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

Referenced by ast_cc_monitor_stop_ringing().

4003 {
4004  struct cc_core_instance *core_instance = data;
4005  int res = 0;
4006 
4007  if (core_instance->agent->callbacks->stop_ringing) {
4008  res = core_instance->agent->callbacks->stop_ringing(core_instance->agent);
4009  }
4010  /* If an agent is being asked to stop ringing, then he needs to be prepared if for
4011  * whatever reason he needs to be called back again. The proper state to be in to
4012  * detect such a circumstance is the CC_ACTIVE state.
4013  *
4014  * We get to this state using the slightly unintuitive method of calling
4015  * ast_cc_monitor_request_acked because it gets us to the proper state.
4016  */
4017  ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.",
4018  core_instance->agent->device_name);
4019  cc_unref(core_instance, "Stop ringing finished. Unref core_instance");
4020  return res;
4021 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
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:3787
int(* stop_ringing)(struct ast_cc_agent *agent)
Request for an agent&#39;s phone to stop ringing.
Definition: ccss.h:1002
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
char device_name[1]
Definition: ccss.h:875
struct ast_cc_agent * agent
Definition: ccss.c:341

◆ cc_unique_append()

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

Definition at line 3558 of file ccss.c.

References AST_CHANNEL_NAME, ast_str_append(), ast_str_buffer(), and ast_strlen_zero.

Referenced by build_cc_interfaces_chanvar().

3559 {
3560  char dialstring_search[AST_CHANNEL_NAME + 1];
3561 
3562  if (ast_strlen_zero(dialstring)) {
3563  /* No dialstring to append. */
3564  return;
3565  }
3566  snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&');
3567  if (strstr(ast_str_buffer(*str), dialstring_search)) {
3568  return;
3569  }
3570  ast_str_append(str, 0, "%s", dialstring_search);
3571 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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:1091
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_CHANNEL_NAME
Definition: channel.h:172

◆ cc_unref()

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

Definition at line 149 of file ccss.c.

References ao2_t_ref, and NULL.

Referenced by ast_cc_agent_callback(), ast_cc_agent_status_response(), ast_cc_available_timer_expire(), ast_cc_call_init(), ast_cc_get_monitor_by_recall_core_id(), ast_cc_monitor_party_b_free(), ast_cc_monitor_status_request(), ast_cc_monitor_stop_ringing(), ast_handle_cc_control_frame(), ast_setup_cc_recall_datastore(), cancel_available_timer(), cc_agent_init(), cc_core_init_instance(), cc_core_instance_destructor(), cc_device_monitor_init(), cc_do_state_change(), cc_extension_monitor_init(), cc_generic_agent_stop_offer_timer(), cc_generic_monitor_cancel_available_timer(), cc_generic_monitor_destructor(), cc_generic_monitor_request_cc(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), cc_interface_tree_destroy(), cc_interfaces_datastore_init(), cc_monitor_destroy(), cc_monitor_failed(), cc_party_b_free(), cc_recall_ds_destroy(), cc_request_state_change(), cc_status_request(), cc_status_response(), cc_stop_ringing(), cccancel_exec(), ccreq_exec(), ccss_device_state(), complete_core_id(), create_new_generic_list(), dialed_cc_interfaces_destroy(), generic_agent_devstate_cb(), generic_monitor_devstate_tp_cb(), offer_timer_expire(), request_cc(), suspend(), and unsuspend().

150 {
151  ao2_t_ref(obj, -1, debug);
152  return NULL;
153 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
static int debug
Global debug status.
Definition: res_xmpp.c:435
#define NULL
Definition: resample.c:96

◆ cccancel_exec()

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

Definition at line 4308 of file ccss.c.

References cc_core_instance::agent, ao2_t_callback_data, ast_cc_failed(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_log, ast_log_dynamic_level, ast_cc_agent::callbacks, cc_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().

4309 {
4310  struct cc_core_instance *core_instance;
4311  char device_name[AST_CHANNEL_NAME];
4312  unsigned long match_flags;
4313  int res;
4314 
4315  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4316 
4317  match_flags = MATCH_REQUEST;
4318  if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) {
4319  ast_log_dynamic_level(cc_logger_level, "Cannot find CC transaction to cancel for caller %s\n", device_name);
4320  pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4321  pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NO_CORE_INSTANCE");
4322  return 0;
4323  }
4324 
4325  if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4326  ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calles with a generic agent\n");
4327  cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4328  pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4329  pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NOT_GENERIC");
4330  return 0;
4331  }
4332  res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s",
4333  core_instance->core_id, device_name);
4334  cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4335  pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", res ? "FAIL" : "SUCCESS");
4336  if (res) {
4337  pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "UNSPECIFIED");
4338  }
4339  return 0;
4340 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define LOG_WARNING
Definition: logger.h:274
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define ast_log
Definition: astobj2.c:42
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:894
match_flags
Definition: ccss.c:469
#define AST_CHANNEL_NAME
Definition: channel.h:172
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:492
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...
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
#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:1741
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
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:10697
struct ast_cc_agent * agent
Definition: ccss.c:341
static int cc_logger_level
Definition: ccss.c:133

◆ ccreq_exec()

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

Definition at line 4257 of file ccss.c.

References cc_core_instance::agent, ao2_t_callback_data, ast_cc_agent_accept_request(), ast_cc_failed(), ast_cc_request_is_within_limits(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_log_dynamic_level, ast_cc_agent::callbacks, cc_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().

4258 {
4259  struct cc_core_instance *core_instance;
4260  char device_name[AST_CHANNEL_NAME];
4261  unsigned long match_flags;
4262  int res;
4263 
4264  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4265 
4266  match_flags = MATCH_NO_REQUEST;
4267  if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) {
4268  ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name);
4269  pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4270  pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NO_CORE_INSTANCE");
4271  return 0;
4272  }
4273 
4274  ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n",
4275  core_instance->core_id, device_name);
4276 
4277  if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4278  ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n",
4279  core_instance->core_id);
4280  pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4281  pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NOT_GENERIC");
4282  cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent");
4283  return 0;
4284  }
4285 
4287  ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n",
4288  core_instance->core_id);
4289  ast_cc_failed(core_instance->core_id, "Too many CC requests\n");
4290  pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4291  pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "TOO_MANY_REQUESTS");
4292  cc_unref(core_instance, "Unref core_instance since too many CC requests");
4293  return 0;
4294  }
4295 
4296  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);
4297  pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS");
4298  if (res) {
4299  pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "UNSPECIFIED");
4300  }
4301 
4302  cc_unref(core_instance, "Done with CallCompletionRequest");
4303  return 0;
4304 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
int ast_cc_agent_accept_request(int core_id, const char *const debug,...)
Accept inbound CC request.
Definition: ccss.c:3776
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
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:2482
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:894
match_flags
Definition: ccss.c:469
#define AST_CHANNEL_NAME
Definition: channel.h:172
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:492
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...
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
#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:1741
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
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:10697
struct ast_cc_agent * agent
Definition: ccss.c:341
static int cc_logger_level
Definition: ccss.c:133

◆ ccss_device_state()

static enum ast_device_state ccss_device_state ( const char *  device_name)
static

Definition at line 600 of file ccss.c.

References cc_core_instance::agent, ao2_t_callback_data, ast_log_dynamic_level, ast_cc_agent::callbacks, 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().

601 {
602  struct cc_core_instance *core_instance;
603  unsigned long match_flags;
604  enum ast_device_state cc_current_state;
605 
606  match_flags = MATCH_NO_REQUEST;
608  (char *) device_name, &match_flags,
609  "Find Core Instance for ccss_device_state reqeust.");
610  if (!core_instance) {
612  "Couldn't find a core instance for caller %s\n", device_name);
614  }
615 
617  "Core %d: Found core_instance for caller %s in state %s\n",
618  core_instance->core_id, device_name, cc_state_to_string(core_instance->current_state));
619 
620  if (strcmp(core_instance->agent->callbacks->type, "generic")) {
622  "Core %d: Device State is only for generic agent types.\n",
623  core_instance->core_id);
624  cc_unref(core_instance, "Unref core_instance since ccss_device_state was called with native agent");
626  }
627  cc_current_state = cc_state_to_devstate(core_instance->current_state);
628  cc_unref(core_instance, "Unref core_instance done with ccss_device_state");
629  return cc_current_state;
630 }
ast_device_state
Device States.
Definition: devicestate.h:52
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
static enum ast_device_state cc_state_to_devstate(enum cc_state state)
Definition: ccss.c:584
static const char * cc_state_to_string(enum cc_state state)
Definition: ccss.c:407
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:894
enum cc_state current_state
Definition: ccss.c:337
match_flags
Definition: ccss.c:469
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:492
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:854
#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:1741
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
struct ast_cc_agent * agent
Definition: ccss.c:341
static int cc_logger_level
Definition: ccss.c:133

◆ ccss_notify_device_state_change()

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

Definition at line 641 of file ccss.c.

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().

642 {
643  enum ast_device_state devstate;
644 
645  devstate = cc_state_to_devstate(state);
646 
648  "Notification of CCSS state change to '%s', device state '%s' for device '%s'\n",
649  cc_state_to_string(state), ast_devstate2str(devstate), device);
650 
651  ast_devstate_changed(devstate, AST_DEVSTATE_CACHABLE, "ccss:%s", device);
652 }
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
ast_device_state
Device States.
Definition: devicestate.h:52
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
static enum ast_device_state cc_state_to_devstate(enum cc_state state)
Definition: ccss.c:584
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510
static const char * cc_state_to_string(enum cc_state state)
Definition: ccss.c:407
static int cc_logger_level
Definition: ccss.c:133

◆ check_callback_sanity()

static void check_callback_sanity ( const struct ast_cc_agent_callbacks callbacks)
static

Definition at line 2532 of file ccss.c.

References ast_assert, ast_cc_agent_callbacks::callee_available, ast_cc_agent_callbacks::destructor, ast_cc_agent_callbacks::init, NULL, ast_cc_agent_callbacks::respond, ast_cc_agent_callbacks::start_monitoring, ast_cc_agent_callbacks::start_offer_timer, ast_cc_agent_callbacks::status_request, and ast_cc_agent_callbacks::stop_offer_timer.

Referenced by cc_agent_init().

2533 {
2534  ast_assert(callbacks->init != NULL);
2535  ast_assert(callbacks->start_offer_timer != NULL);
2536  ast_assert(callbacks->stop_offer_timer != NULL);
2537  ast_assert(callbacks->respond != NULL);
2538  ast_assert(callbacks->status_request != NULL);
2539  ast_assert(callbacks->start_monitoring != NULL);
2540  ast_assert(callbacks->callee_available != NULL);
2541  ast_assert(callbacks->destructor != NULL);
2542 }
int(* status_request)(struct ast_cc_agent *agent)
Request the status of the agent&#39;s device.
Definition: ccss.h:980
int(* start_offer_timer)(struct ast_cc_agent *agent)
Start the offer timer.
Definition: ccss.h:934
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
int(* start_monitoring)(struct ast_cc_agent *agent)
Begin monitoring a busy device.
Definition: ccss.h:1039
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition: ccss.h:965
int(* callee_available)(struct ast_cc_agent *agent)
Alert the caller that it is time to try recalling.
Definition: ccss.h:1058
int(* init)(struct ast_cc_agent *agent, struct ast_channel *chan)
CC agent initialization.
Definition: ccss.h:913
void(* destructor)(struct ast_cc_agent *agent)
Destroy private data on the agent.
Definition: ccss.h:1072
int(* stop_offer_timer)(struct ast_cc_agent *agent)
Stop the offer timer.
Definition: ccss.h:947

◆ complete_core_id()

static char* complete_core_id ( const char *  word)
static

Definition at line 4555 of file ccss.c.

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

Referenced by handle_cc_kill().

4556 {
4557  int wordlen = strlen(word);
4558  struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0);
4559  struct cc_core_instance *core_instance;
4560 
4561  for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance"));
4562  cc_unref(core_instance, "CLI tab completion iteration")) {
4563  char core_id_str[20];
4564  snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id);
4565  if (!strncmp(word, core_id_str, wordlen)) {
4566  if (ast_cli_completion_add(ast_strdup(core_id_str))) {
4567  cc_unref(core_instance, "Found a matching core ID for CLI tab-completion");
4568  break;
4569  }
4570  }
4571  }
4572  ao2_iterator_destroy(&core_iter);
4573 
4574  return NULL;
4575 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2726
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
short word

◆ count_agents()

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

Definition at line 2506 of file ccss.c.

References ao2_t_callback_data, ast_log_dynamic_level, 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().

2507 {
2509 
2510  ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents");
2511  ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count);
2512  return data.count;
2513 }
static int count_agents_cb(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:530
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
int core_id_exception
Definition: ccss.c:519
#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:1741
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
static int cc_logger_level
Definition: ccss.c:133

◆ count_agents_cb()

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

Definition at line 530 of file ccss.c.

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().

531 {
532  struct cc_core_instance *core_instance = obj;
533  const char *name = arg;
534  struct count_agents_cb_data *cb_data = data;
535 
536  if (cb_data->core_id_exception == core_instance->core_id) {
537  ast_log_dynamic_level(cc_logger_level, "Found agent with core_id %d but not counting it toward total\n", core_instance->core_id);
538  return 0;
539  }
540 
541  if (core_instance->current_state >= CC_CALLER_REQUESTED && !strcmp(core_instance->agent->device_name, name)) {
542  cb_data->count++;
543  }
544  return 0;
545 }
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
int core_id_exception
Definition: ccss.c:519
enum cc_state current_state
Definition: ccss.c:337
static const char name[]
Definition: cdr_mysql.c:74
char device_name[1]
Definition: ccss.h:875
struct ast_cc_agent * agent
Definition: ccss.c:341
static int cc_logger_level
Definition: ccss.c:133

◆ count_monitors_cb()

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

Definition at line 4348 of file ccss.c.

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

Referenced by ast_cc_monitor_count().

4349 {
4350  struct cc_core_instance *core_instance = obj;
4351  struct count_monitors_cb_data *cb_data = arg;
4352  const char *device_name = cb_data->device_name;
4353  const char *monitor_type = cb_data->monitor_type;
4354  struct ast_cc_monitor *monitor_iter;
4355 
4356  AST_LIST_LOCK(core_instance->monitors);
4357  AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
4358  if (!strcmp(monitor_iter->interface->device_name, device_name) &&
4359  !strcmp(monitor_iter->interface->monitor_type, monitor_type)) {
4360  cb_data->count++;
4361  break;
4362  }
4363  }
4364  AST_LIST_UNLOCK(core_instance->monitors);
4365  return 0;
4366 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
struct ast_cc_monitor * next
Definition: ccss.h:562
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
const char * monitor_type
Definition: ccss.c:4344
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
const char * monitor_type
The type of monitor that should be used for this interface.
Definition: ccss.h:830
struct ast_cc_interface * interface
Definition: ccss.h:514
char device_name[1]
Definition: ccss.h:839
const char * device_name
Definition: ccss.c:4343

◆ create_new_generic_list()

static struct generic_monitor_instance_list* create_new_generic_list ( struct ast_cc_monitor monitor)
static

Definition at line 1409 of file ccss.c.

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_instance_list_destructor(), 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().

1410 {
1411  struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list),
1412  generic_monitor_instance_list_destructor, "allocate generic monitor instance list");
1413  char * device_name;
1414  struct stasis_topic *device_specific_topic;
1415 
1416  if (!generic_list) {
1417  return NULL;
1418  }
1419 
1420  if (!(device_name = ast_strdup(monitor->interface->device_name))) {
1421  cc_unref(generic_list, "Failed to strdup the monitor's device name");
1422  return NULL;
1423  }
1424  ast_tech_to_upper(device_name);
1425  generic_list->device_name = device_name;
1426 
1427  device_specific_topic = ast_device_state_topic(device_name);
1428  if (!device_specific_topic) {
1429  return NULL;
1430  }
1431 
1432  if (!(generic_list->sub = stasis_subscribe(device_specific_topic, generic_monitor_devstate_cb, NULL))) {
1433  cc_unref(generic_list, "Failed to subscribe to device state");
1434  return NULL;
1435  }
1438  generic_list->current_state = ast_device_state(monitor->interface->device_name);
1439  ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list");
1440  return generic_list;
1441 }
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
Definition: devicestate.c:683
ast_device_state
Device States.
Definition: devicestate.h:52
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:409
static void generic_monitor_devstate_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: ccss.c:1484
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
static void generic_monitor_instance_list_destructor(void *obj)
Definition: ccss.c:1396
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:1079
#define ao2_t_link(container, obj, tag)
Add an object to a container.
Definition: astobj2.h:1547
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_subscription * sub
Definition: ccss.c:1361
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
struct ao2_container * generic_monitors
Definition: ccss.c:1333
char * ast_tech_to_upper(char *dev_str)
Convert the tech portion of a device string to upper case.
Definition: strings.h:1183
struct ast_cc_interface * interface
Definition: ccss.h:514
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:1025
char device_name[1]
Definition: ccss.h:839
enum ast_device_state current_state
Definition: ccss.c:1344
const char * device_name
Definition: ccss.c:1343

◆ dialed_cc_interfaces_destroy()

static void dialed_cc_interfaces_destroy ( void *  data)
static

Definition at line 1944 of file ccss.c.

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

1945 {
1946  struct dialed_cc_interfaces *cc_interfaces = data;
1947  cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree");
1948  ast_free(cc_interfaces);
1949 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define ast_free(a)
Definition: astmm.h:182
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1929

◆ dialed_cc_interfaces_duplicate()

static void* dialed_cc_interfaces_duplicate ( void *  data)
static

Definition at line 1964 of file ccss.c.

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.

1965 {
1966  struct dialed_cc_interfaces *old_cc_interfaces = data;
1967  struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces));
1968  if (!new_cc_interfaces) {
1969  return NULL;
1970  }
1971  new_cc_interfaces->ignore = old_cc_interfaces->ignore;
1972  new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id;
1973  new_cc_interfaces->is_original_caller = 0;
1974  cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree");
1975  new_cc_interfaces->core_id = old_cc_interfaces->core_id;
1976  new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree;
1977  return new_cc_interfaces;
1978 }
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:143
#define NULL
Definition: resample.c:96
char is_original_caller
Definition: ccss.c:1925
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1929
unsigned int dial_parent_id
Definition: ccss.c:1902

◆ extension_monitor_pvt_init()

static struct extension_monitor_pvt* extension_monitor_pvt_init ( void  )
static

Definition at line 1995 of file ccss.c.

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

Referenced by cc_extension_monitor_init().

1996 {
1997  struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt));
1998  if (!ext_pvt) {
1999  return NULL;
2000  }
2002  return ext_pvt;
2003 }
#define NULL
Definition: resample.c:96
struct extension_monitor_pvt::@366 child_dialstrings
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
Private data for an extension monitor.
Definition: ccss.c:1817

◆ find_agent_callbacks()

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

Definition at line 1269 of file ccss.c.

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

Referenced by cc_agent_init().

1270 {
1271  struct cc_agent_backend *backend;
1272  const struct ast_cc_agent_callbacks *callbacks = NULL;
1273  struct ast_cc_config_params *cc_params;
1274  char type[32];
1275 
1276  cc_params = ast_channel_get_cc_config_params(chan);
1277  if (!cc_params) {
1278  return NULL;
1279  }
1280  switch (ast_get_cc_agent_policy(cc_params)) {
1281  case AST_CC_AGENT_GENERIC:
1282  ast_copy_string(type, "generic", sizeof(type));
1283  break;
1284  case AST_CC_AGENT_NATIVE:
1285  ast_channel_get_cc_agent_type(chan, type, sizeof(type));
1286  break;
1287  default:
1288  ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n");
1289  return NULL;
1290  }
1291 
1293  AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) {
1294  if (!strcmp(backend->callbacks->type, type)) {
1295  ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type);
1296  callbacks = backend->callbacks;
1297  break;
1298  }
1299  }
1301  return callbacks;
1302 }
static const char type[]
Definition: chan_ooh323.c:109
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define NULL
Definition: resample.c:96
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:10675
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const struct ast_cc_agent_callbacks * callbacks
Definition: ccss.c:1234
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
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:10714
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:894
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:866
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int cc_logger_level
Definition: ccss.c:133

◆ find_cc_core_instance()

static struct cc_core_instance* find_cc_core_instance ( const int  core_id)
static

Definition at line 431 of file ccss.c.

References ao2_t_find, cc_core_instance::core_id, and OBJ_POINTER.

Referenced by ast_cc_agent_status_response(), ast_cc_get_monitor_by_recall_core_id(), ast_cc_monitor_party_b_free(), ast_cc_monitor_status_request(), ast_cc_monitor_stop_ringing(), ast_handle_cc_control_frame(), ast_setup_cc_recall_datastore(), cc_monitor_failed(), and cc_request_state_change().

432 {
433  struct cc_core_instance finder = {.core_id = core_id,};
434 
435  return ao2_t_find(cc_core_instances, &finder, OBJ_POINTER, "Finding a core_instance");
436 }
#define OBJ_POINTER
Definition: astobj2.h:1154
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
#define ao2_t_find(container, arg, flags, tag)
Definition: astobj2.h:1754

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

References ao2_t_find, ast_strdupa, ast_tech_to_upper(), generic_monitor_instance_list::device_name, 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().

1387 {
1388  struct generic_monitor_instance_list finder = {0};
1389  char *uppertech = ast_strdupa(device_name);
1390  ast_tech_to_upper(uppertech);
1391  finder.device_name = uppertech;
1392 
1393  return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list");
1394 }
#define OBJ_POINTER
Definition: astobj2.h:1154
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ao2_container * generic_monitors
Definition: ccss.c:1333
char * ast_tech_to_upper(char *dev_str)
Convert the tech portion of a device string to upper case.
Definition: strings.h:1183
#define ao2_t_find(container, arg, flags, tag)
Definition: astobj2.h:1754
const char * device_name
Definition: ccss.c:1343

◆ find_monitor_callbacks()

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

Definition at line 1200 of file ccss.c.

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

Referenced by call_destructor_with_no_monitor(), and cc_device_monitor_init().

1201 {
1202  struct cc_monitor_backend *backend;
1203  const struct ast_cc_monitor_callbacks *callbacks = NULL;
1204 
1206  AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) {
1207  if (!strcmp(backend->callbacks->type, type)) {
1208  ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type);
1209  callbacks = backend->callbacks;
1210  break;
1211  }
1212  }
1214  return callbacks;
1215 }
static const char type[]
Definition: chan_ooh323.c:109
const char * type
Type of monitor the callbacks belong to.
Definition: ccss.h:583
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define NULL
Definition: resample.c:96
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.c:1179
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
Callbacks defined by CC monitors.
Definition: ccss.h:576
static int cc_logger_level
Definition: ccss.c:133

◆ generic_agent_devstate_cb()

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

Definition at line 2761 of file ccss.c.

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, and cc_generic_agent_pvt::sub.

Referenced by cc_generic_agent_start_monitoring().

2762 {
2763  struct ast_cc_agent *agent = userdata;
2764  enum ast_device_state new_state;
2765  struct ast_device_state_message *dev_state;
2766  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2767 
2768  if (stasis_subscription_final_message(sub, msg)) {
2769  cc_unref(agent, "Done holding ref for subscription");
2770  return;
2771  } else if (ast_device_state_message_type() != stasis_message_type(msg)) {
2772  return;
2773  }
2774 
2775  dev_state = stasis_message_data(msg);
2776  if (dev_state->eid) {
2777  /* ignore non-aggregate states */
2778  return;
2779  }
2780 
2781  new_state = dev_state->state;
2782  if (!cc_generic_is_device_available(new_state)) {
2783  /* Not interested in this new state of the device. It is still busy. */
2784  return;
2785  }
2786 
2787  generic_pvt->sub = stasis_unsubscribe(sub);
2788  ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name);
2789 }
ast_device_state
Device States.
Definition: devicestate.h:52
void * private_data
Definition: ccss.h:871
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
enum ast_device_state state
Definition: devicestate.h:250
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_subscription * sub
Definition: ccss.c:2628
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:973
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:1176
unsigned int core_id
Definition: ccss.h:849
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:3820
char device_name[1]
Definition: ccss.h:875
The structure that contains device state.
Definition: devicestate.h:240
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1313

◆ generic_monitor_devstate_cb()

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

Definition at line 1484 of file ccss.c.

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

Referenced by generic_monitor_instance_list_destructor().

1485 {
1486  /* Wow, it's cool that we've picked up on a state change, but we really want
1487  * the actual work to be done in the core's taskprocessor execution thread
1488  * so that all monitor operations can be serialized. Locks?! We don't need
1489  * no steenkin' locks!
1490  */
1491  struct ast_device_state_message *dev_state;
1493  return;
1494  }
1495 
1496  dev_state = stasis_message_data(msg);
1497  if (dev_state->eid) {
1498  /* ignore non-aggregate states */
1499  return;
1500  }
1501 
1502  ao2_t_ref(dev_state, +1, "Bumping dev_state ref for cc_core_taskprocessor");
1504  ao2_cleanup(dev_state);
1505  return;
1506  }
1507 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
static int generic_monitor_devstate_tp_cb(void *data)
Definition: ccss.c:1443
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
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.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
The structure that contains device state.
Definition: devicestate.h:240
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

◆ generic_monitor_devstate_tp_cb()

static int generic_monitor_devstate_tp_cb ( void *  data)
static

Definition at line 1443 of file ccss.c.

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().

1444 {
1445  RAII_VAR(struct ast_device_state_message *, dev_state, data, ao2_cleanup);
1446  enum ast_device_state new_state = dev_state->state;
1447  enum ast_device_state previous_state;
1448  struct generic_monitor_instance_list *generic_list;
1449  struct generic_monitor_instance *generic_instance;
1450 
1451  if (!(generic_list = find_generic_monitor_instance_list(dev_state->device))) {
1452  /* The most likely cause for this is that we destroyed the monitor in the
1453  * time between subscribing to its device state and the time this executes.
1454  * Not really a big deal.
1455  */
1456  return 0;
1457  }
1458 
1459  if (generic_list->current_state == new_state) {
1460  /* The device state hasn't actually changed, so we don't really care */
1461  cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1462  return 0;
1463  }
1464 
1465  previous_state = generic_list->current_state;
1466  generic_list->current_state = new_state;
1467 
1468  if (cc_generic_is_device_available(new_state) &&
1469  (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE ||
1470  previous_state == AST_DEVICE_BUSY)) {
1471  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1472  if (!generic_instance->is_suspended && generic_instance->monitoring) {
1473  generic_instance->monitoring = 0;
1474  generic_list->fit_for_recall = 1;
1475  ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1476  break;
1477  }
1478  }
1479  }
1480  cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1481  return 0;
1482 }
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:3798
ast_device_state
Device States.
Definition: devicestate.h:52
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#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:911
struct generic_monitor_instance_list::@364 list
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1386
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
The structure that contains device state.
Definition: devicestate.h:240
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1313
enum ast_device_state current_state
Definition: ccss.c:1344
struct generic_monitor_instance * next
Definition: ccss.c:1339

◆ generic_monitor_instance_list_destructor()

static void generic_monitor_instance_list_destructor ( void *  obj)
static

Definition at line 1396 of file ccss.c.

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

Referenced by create_new_generic_list().

1397 {
1398  struct generic_monitor_instance_list *generic_list = obj;
1399  struct generic_monitor_instance *generic_instance;
1400 
1401  generic_list->sub = stasis_unsubscribe(generic_list->sub);
1402  while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) {
1403  ast_free(generic_instance);
1404  }
1405  ast_free((char *)generic_list->device_name);
1406 }
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
struct stasis_subscription * sub
Definition: ccss.c:1361
struct generic_monitor_instance_list::@364 list
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:973
#define ast_free(a)
Definition: astmm.h:182
const char * device_name
Definition: ccss.c:1343
struct generic_monitor_instance * next
Definition: ccss.c:1339

◆ generic_recall()

static void* generic_recall ( void *  data)
static

Definition at line 2816 of file ccss.c.

References ao2_ref, ast_app_exec_macro(), 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_callback_macro(), 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_strlen_zero, cc_logger_level, cc_generic_agent_pvt::cid_name, cc_generic_agent_pvt::cid_num, cc_generic_agent_pvt::context, cc_generic_agent_pvt::exten, NULL, pbx_builtin_setvar_helper(), ast_cc_agent::private_data, and S_OR.

Referenced by cc_generic_agent_recall().

2817 {
2818  struct ast_cc_agent *agent = data;
2819  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2820  const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name));
2821  const char *tech;
2822  char *target;
2823  int reason;
2824  struct ast_channel *chan;
2825  const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
2826  const char *callback_sub = ast_get_cc_callback_sub(agent->cc_params);
2827  unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
2829 
2830  if (!tmp_cap) {
2831  return NULL;
2832  }
2833 
2834  tech = interface;
2835  if ((target = strchr(interface, '/'))) {
2836  *target++ = '\0';
2837  }
2838 
2840  if (!(chan = ast_request_and_dial(tech, tmp_cap, NULL, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
2841  /* Hmm, no channel. Sucks for you, bud.
2842  */
2843  ast_log_dynamic_level(cc_logger_level, "Core %u: Failed to call back %s for reason %d\n",
2844  agent->core_id, agent->device_name, reason);
2845  ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target);
2846  ao2_ref(tmp_cap, -1);
2847  return NULL;
2848  }
2849  ao2_ref(tmp_cap, -1);
2850 
2851  /* We have a channel. It's time now to set up the datastore of recalled CC interfaces.
2852  * This will be a common task for all recall functions. If it were possible, I'd have
2853  * the core do it automatically, but alas I cannot. Instead, I will provide a public
2854  * function to do so.
2855  */
2856  ast_setup_cc_recall_datastore(chan, agent->core_id);
2858 
2859  ast_channel_exten_set(chan, generic_pvt->exten);
2860  ast_channel_context_set(chan, generic_pvt->context);
2861  ast_channel_priority_set(chan, 1);
2862 
2863  pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten);
2864  pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context);
2865 
2866  if (!ast_strlen_zero(callback_macro)) {
2867  ast_log_dynamic_level(cc_logger_level, "Core %u: There's a callback macro configured for agent %s\n",
2868  agent->core_id, agent->device_name);
2869  if (ast_app_exec_macro(NULL, chan, callback_macro)) {
2870  ast_cc_failed(agent->core_id, "Callback macro to %s failed. Maybe a hangup?", agent->device_name);
2871  ast_hangup(chan);
2872  return NULL;
2873  }
2874  }
2875 
2876  if (!ast_strlen_zero(callback_sub)) {
2877  ast_log_dynamic_level(cc_logger_level, "Core %u: There's a callback subroutine configured for agent %s\n",
2878  agent->core_id, agent->device_name);
2879  if (ast_app_exec_sub(NULL, chan, callback_sub, 0)) {
2880  ast_cc_failed(agent->core_id, "Callback subroutine to %s failed. Maybe a hangup?", agent->device_name);
2881  ast_hangup(chan);
2882  return NULL;
2883  }
2884  }
2885  if (ast_pbx_start(chan)) {
2886  ast_cc_failed(agent->core_id, "PBX failed to start for %s.", agent->device_name);
2887  ast_hangup(chan);
2888  return NULL;
2889  }
2890  ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling",
2891  agent->device_name);
2892  return NULL;
2893 }
Main Channel structure associated with a channel.
void * private_data
Definition: ccss.h:871
char cid_num[AST_CHANNEL_NAME]
Definition: ccss.c:2642
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:6264
unsigned int ast_get_cc_recall_timer(struct ast_cc_config_params *config)
Get the cc_recall_timer.
Definition: ccss.c:930
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
struct ast_cc_config_params * cc_params
Definition: ccss.h:859
char context[AST_CHANNEL_NAME]
Definition: ccss.c:2666
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:3405
char exten[AST_CHANNEL_NAME]
Definition: ccss.c:2658
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:3831
const char * ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
Get the cc_agent_dialstring.
Definition: ccss.c:960
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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:3631
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
int ast_app_exec_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char *macro_args)
Run a macro on a channel, placing an optional second channel into autoservice.
Definition: main/app.c:273
const char * ast_get_cc_callback_macro(struct ast_cc_config_params *config)
Get the name of the callback_macro.
Definition: ccss.c:994
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
unsigned int core_id
Definition: ccss.h:849
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
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 device_name[1]
Definition: ccss.h:875
void ast_channel_context_set(struct ast_channel *chan, const char *value)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
char cid_name[AST_CHANNEL_NAME]
Definition: ccss.c:2650
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:370
const char * ast_get_cc_callback_sub(struct ast_cc_config_params *config)
Get the name of the callback subroutine.
Definition: ccss.c:999
static int cc_logger_level
Definition: ccss.c:133
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

◆ handle_cc_kill()

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

Definition at line 4577 of file ccss.c.

References ao2_t_callback, ast_cli_args::argc, ast_cli_args::argv, 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, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

4578 {
4579  switch (cmd) {
4580  case CLI_INIT:
4581  e->command = "cc cancel [core|all]";
4582  e->usage =
4583  "Usage: cc cancel can be used in two ways.\n"
4584  " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n"
4585  " core ID equal to the specified core ID.\n"
4586  " 2. 'cc cancel all' will cancel all active CC transactions.\n";
4587  return NULL;
4588  case CLI_GENERATE:
4589  if (a->pos == 3 && !strcasecmp(a->argv[2], "core")) {
4590  return complete_core_id(a->word);
4591  }
4592  return NULL;
4593  }
4594 
4595  if (a->argc == 4) {
4596  int core_id;
4597  char *endptr;
4598  if (strcasecmp(a->argv[2], "core")) {
4599  return CLI_SHOWUSAGE;
4600  }
4601  core_id = strtol(a->argv[3], &endptr, 10);
4602  if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) {
4603  return CLI_SHOWUSAGE;
4604  }
4605  ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id");
4606  } else if (a->argc == 3) {
4607  if (strcasecmp(a->argv[2], "all")) {
4608  return CLI_SHOWUSAGE;
4609  }
4610  ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores");
4611  } else {
4612  return CLI_SHOWUSAGE;
4613  }
4614 
4615  return CLI_SUCCESS;
4616 }
static char * complete_core_id(const char *word)
Definition: ccss.c:4555
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
int errno
static int kill_cores(void *obj, void *arg, int flags)
Definition: ccss.c:4544
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1714
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
const int pos
Definition: cli.h:164
static struct ao2_container * cc_core_instances
Definition: ccss.c:327

◆ handle_cc_status()

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

Definition at line 4511 of file ccss.c.

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

4512 {
4513  int *cli_fd;
4514 
4515  switch (cmd) {
4516  case CLI_INIT:
4517  e->command = "cc report status";
4518  e->usage =
4519  "Usage: cc report status\n"
4520  " Report the current status of any ongoing CC transactions\n";
4521  return NULL;
4522  case CLI_GENERATE:
4523  return NULL;
4524  }
4525 
4526  if (a->argc != 3) {
4527  return CLI_SHOWUSAGE;
4528  }
4529 
4530  cli_fd = ast_malloc(sizeof(*cli_fd));
4531  if (!cli_fd) {
4532  return CLI_FAILURE;
4533  }
4534 
4535  *cli_fd = a->fd;
4536 
4538  ast_free(cli_fd);
4539  return CLI_FAILURE;
4540  }
4541  return CLI_SUCCESS;
4542 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
const int fd
Definition: cli.h:159
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_FAILURE
Definition: cli.h:46
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static int cc_cli_output_status(void *data)
Definition: ccss.c:4494
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

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

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

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

3094 {
3095  struct ast_cc_monitor *iter;
3096  int res = 0;
3097 
3098  AST_LIST_TRAVERSE(core_instance->monitors, iter, next) {
3100  res = 1;
3101  break;
3102  }
3103  }
3104 
3105  return res;
3106 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
struct ast_cc_monitor * next
Definition: ccss.h:562
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_cc_interface * interface
Definition: ccss.h:514
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

◆ initialize_cc_devstate_map()

static void initialize_cc_devstate_map ( void  )
static

Definition at line 4436 of file ccss.c.

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().

4437 {
4438  struct ast_config *cc_config;
4439  struct ast_flags config_flags = { 0, };
4440 
4441  cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
4442  if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
4444  "Could not find valid ccss.conf file. Using cc_[state]_devstate defaults\n");
4445  return;
4446  }
4447 
4448  initialize_cc_devstate_map_helper(cc_config, CC_AVAILABLE, "cc_available_devstate");
4449  initialize_cc_devstate_map_helper(cc_config, CC_CALLER_OFFERED, "cc_caller_offered_devstate");
4450  initialize_cc_devstate_map_helper(cc_config, CC_CALLER_REQUESTED, "cc_caller_requested_devstate");
4451  initialize_cc_devstate_map_helper(cc_config, CC_ACTIVE, "cc_active_devstate");
4452  initialize_cc_devstate_map_helper(cc_config, CC_CALLEE_READY, "cc_callee_ready_devstate");
4453  initialize_cc_devstate_map_helper(cc_config, CC_CALLER_BUSY, "cc_caller_busy_devstate");
4454  initialize_cc_devstate_map_helper(cc_config, CC_RECALLING, "cc_recalling_devstate");
4455  initialize_cc_devstate_map_helper(cc_config, CC_COMPLETE, "cc_complete_devstate");
4456  initialize_cc_devstate_map_helper(cc_config, CC_FAILED, "cc_failed_devstate");
4457 
4458  ast_config_destroy(cc_config);
4459 }
#define LOG_WARNING
Definition: logger.h:274
#define CONFIG_STATUS_FILEINVALID
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:3154
#define ast_log
Definition: astobj2.c:42
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
Structure used to handle boolean flags.
Definition: utils.h:199
static void initialize_cc_devstate_map_helper(struct ast_config *cc_config, enum cc_state state, const char *cc_setting)
Definition: ccss.c:4412

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

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

Referenced by initialize_cc_devstate_map().

4413 {
4414  const char *cc_devstate_str;
4415  enum ast_device_state this_devstate;
4416 
4417  if ((cc_devstate_str = ast_variable_retrieve(cc_config, "general", cc_setting))) {
4418  this_devstate = ast_devstate_val(cc_devstate_str);
4419  if (this_devstate != AST_DEVICE_UNKNOWN) {
4420  cc_state_to_devstate_map[state] = this_devstate;
4421  }
4422  }
4423 }
ast_device_state
Device States.
Definition: devicestate.h:52
enum cc_state state
Definition: ccss.c:393
static enum ast_device_state cc_state_to_devstate_map[]
Definition: ccss.c:563
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
Definition: devicestate.c:260
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694

◆ initialize_cc_max_requests()

static void initialize_cc_max_requests ( void  )
static

Definition at line 4377 of file ccss.c.

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().

4378 {
4379  struct ast_config *cc_config;
4380  const char *cc_max_requests_str;
4381  struct ast_flags config_flags = {0,};
4382  char *endptr;
4383 
4384  cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
4385  if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
4386  ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests default\n");
4388  return;
4389  }
4390 
4391  if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) {
4392  ast_config_destroy(cc_config);
4394  return;
4395  }
4396 
4397  global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10);
4398 
4399  if (!ast_strlen_zero(endptr)) {
4400  ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n");
4402  }
4403 
4404  ast_config_destroy(cc_config);
4405  return;
4406 }
static unsigned int global_cc_max_requests
Definition: ccss.c:137
#define LOG_WARNING
Definition: logger.h:274
#define CONFIG_STATUS_FILEINVALID
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:3154
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
Structure used to handle boolean flags.
Definition: utils.h:199
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define GLOBAL_CC_MAX_REQUESTS_DEFAULT
Definition: ccss.c:660

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

References 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, and ast_cc_agent::core_id.

Referenced by cc_do_state_change().

3002 {
3003  int is_valid = 0;
3004  switch (new_state) {
3005  case CC_AVAILABLE:
3006  ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to state %u? That should never happen.\n",
3007  agent->core_id, new_state);
3008  break;
3009  case CC_CALLER_OFFERED:
3010  if (current_state == CC_AVAILABLE) {
3011  is_valid = 1;
3012  }
3013  break;
3014  case CC_CALLER_REQUESTED:
3015  if (current_state == CC_CALLER_OFFERED ||
3016  (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) {
3017  is_valid = 1;
3018  }
3019  break;
3020  case CC_ACTIVE:
3021  if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) {
3022  is_valid = 1;
3023  }
3024  break;
3025  case CC_CALLEE_READY:
3026  if (current_state == CC_ACTIVE) {
3027  is_valid = 1;
3028  }
3029  break;
3030  case CC_CALLER_BUSY:
3031  if (current_state == CC_CALLEE_READY) {
3032  is_valid = 1;
3033  }
3034  break;
3035  case CC_RECALLING:
3036  if (current_state == CC_CALLEE_READY) {
3037  is_valid = 1;
3038  }
3039  break;
3040  case CC_COMPLETE:
3041  if (current_state == CC_RECALLING) {
3042  is_valid = 1;
3043  }
3044  break;
3045  case CC_FAILED:
3046  is_valid = 1;
3047  break;
3048  default:
3049  ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to unknown state %u\n",
3050  agent->core_id, new_state);
3051  break;
3052  }
3053 
3054  return is_valid;
3055 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
unsigned int core_id
Definition: ccss.h:849
static int cc_logger_level
Definition: ccss.c:133

◆ kill_cores()

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

Definition at line 4544 of file ccss.c.

References ast_cc_failed(), and cc_core_instance::core_id.

Referenced by handle_cc_kill().

4545 {
4546  int *core_id = arg;
4547  struct cc_core_instance *core_instance = obj;
4548 
4549  if (!core_id || (core_instance->core_id == *core_id)) {
4550  ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n");
4551  }
4552  return 0;
4553 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879

◆ kill_duplicate_offers()

static void kill_duplicate_offers ( char *  caller)
static

Definition at line 2515 of file ccss.c.

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

Referenced by cc_core_init_instance().

2516 {
2517  unsigned long match_flags = MATCH_NO_REQUEST;
2518  struct ao2_iterator *dups_iter;
2519 
2520  /*
2521  * Must remove the ref that was in cc_core_instances outside of
2522  * the container lock to prevent deadlock.
2523  */
2525  match_agent, caller, &match_flags, "Killing duplicate offers");
2526  if (dups_iter) {
2527  /* Now actually unref any duplicate offers by simply destroying the iterator. */
2528  ao2_iterator_destroy(dups_iter);
2529  }
2530 }
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
match_flags
Definition: ccss.c:469
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:492
#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:1741
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static struct ao2_container * cc_core_instances
Definition: ccss.c:327

◆ load_module()

static int load_module ( void  )
static

Definition at line 4653 of file ccss.c.

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_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CORE, AST_MODULE_INFO(), AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_CORE, ast_register_application2(), ast_sched_context_create(), ast_sched_start_thread(), ast_taskprocessor_get(), ASTERISK_GPL_KEY, cc_core_instance_cmp_fn(), cc_core_instance_hash_fn(), CC_CORE_INSTANCES_BUCKETS, cc_logger_level, CC_LOGGER_LEVEL_NAME, cccancel_exec(), ccreq_exec(), ccss_device_state(), initialize_cc_devstate_map(), initialize_cc_max_requests(), NULL, TPS_REF_DEFAULT, and unload_module().

4654 {
4655  int res;
4656 
4660  "Create core instance container");
4661  if (!cc_core_instances) {
4662  return AST_MODULE_LOAD_FAILURE;
4663  }
4664 
4667  generic_monitor_instance_list_hash_fn, NULL, generic_monitor_instance_list_cmp_fn,
4668  "Create generic monitor container");
4669  if (!generic_monitors) {
4670  return AST_MODULE_LOAD_FAILURE;
4671  }
4673  return AST_MODULE_LOAD_FAILURE;
4674  }
4676  return AST_MODULE_LOAD_FAILURE;
4677  }
4679  return AST_MODULE_LOAD_FAILURE;
4680  }
4685 
4690 
4691  /* Read the map and register the device state callback for generic agents */
4693  res |= ast_devstate_prov_add("ccss", ccss_device_state);
4694 
4696 }
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:195
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int dialed_cc_interface_counter
Definition: ccss.c:1875
static const int CC_CORE_INSTANCES_BUCKETS
Definition: ccss.c:326
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...
return a reference to a taskprocessor, create one if it does not exist
Definition: taskprocessor.h:75
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:391
static const char * ccreq_app
Definition: ccss.c:4255
#define NULL
Definition: resample.c:96
static const char * CC_LOGGER_LEVEL_NAME
Definition: ccss.c:129
static struct ast_sched_context * cc_sched_context
Definition: ccss.c:115
static int cccancel_exec(struct ast_channel *chan, const char *data)
Definition: ccss.c:4308
static struct ast_cli_entry cc_cli[]
Definition: ccss.c:4618
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:2503
static void initialize_cc_devstate_map(void)
Definition: ccss.c:4436
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236
static int ccreq_exec(struct ast_channel *chan, const char *data)
Definition: ccss.c:4257
struct ao2_container * generic_monitors
Definition: ccss.c:1333
static struct ast_cc_agent_callbacks generic_agent_callbacks
Definition: ccss.c:2606
static int cc_core_instance_cmp_fn(void *obj, void *arg, int flags)
Definition: ccss.c:423
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition: ccss.c:1184
Module could not be loaded properly.
Definition: module.h:102
#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1308
static void initialize_cc_max_requests(void)
Definition: ccss.c:4377
static enum ast_device_state ccss_device_state(const char *device_name)
Definition: ccss.c:600
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition: pbx_app.c:103
static struct ast_cc_monitor_callbacks generic_monitor_cbs
Definition: ccss.c:1324
static const char * cccancel_app
Definition: ccss.c:4306
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:1239
static int cc_logger_level
Definition: ccss.c:133
static int cc_core_instance_hash_fn(const void *obj, const int flags)
Definition: ccss.c:417
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

◆ match_agent()

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

Definition at line 492 of file ccss.c.

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

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

493 {
494  struct cc_core_instance *core_instance = obj;
495  const char *name = arg;
496  unsigned long match_flags = *(unsigned long *)data;
497  int possible_match = 0;
498 
499  if ((match_flags & MATCH_NO_REQUEST) && core_instance->current_state < CC_CALLER_REQUESTED) {
500  possible_match = 1;
501  }
502 
503  if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) {
504  possible_match = 1;
505  }
506 
507  if (!possible_match) {
508  return 0;
509  }
510 
511  if (!strcmp(core_instance->agent->device_name, name)) {
512  return CMP_MATCH | CMP_STOP;
513  }
514  return 0;
515 }
enum cc_state current_state
Definition: ccss.c:337
static const char name[]
Definition: cdr_mysql.c:74
match_flags
Definition: ccss.c:469
char device_name[1]
Definition: ccss.h:875
struct ast_cc_agent * agent
Definition: ccss.c:341

◆ monitor_policy_to_str()

static const char* monitor_policy_to_str ( enum ast_cc_monitor_policies  policy)
static

Definition at line 743 of file ccss.c.

References AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, and AST_CC_MONITOR_NEVER.

Referenced by ast_cc_get_param().

744 {
745  switch (policy) {
747  return "never";
749  return "native";
751  return "generic";
753  return "always";
754  default:
755  /* This should never happen... */
756  return "";
757  }
758 }

◆ offer_timer_expire()

static int offer_timer_expire ( const void *  data)
static

Definition at line 2691 of file ccss.c.

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

Referenced by cc_generic_agent_start_offer_timer().

2692 {
2693  struct ast_cc_agent *agent = (struct ast_cc_agent *) data;
2694  struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
2695  ast_log_dynamic_level(cc_logger_level, "Core %u: Queuing change request because offer timer has expired.\n",
2696  agent->core_id);
2697  agent_pvt->offer_timer_id = -1;
2698  ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name);
2699  cc_unref(agent, "Remove scheduler's reference to the agent");
2700  return 0;
2701 }
void * private_data
Definition: ccss.h:871
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
Structure representing an agent.
unsigned int core_id
Definition: ccss.h:849
char device_name[1]
Definition: ccss.h:875
static int cc_logger_level
Definition: ccss.c:133

◆ print_stats_cb()

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

Definition at line 4481 of file ccss.c.

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

Referenced by cc_cli_output_status().

4482 {
4483  int *cli_fd = arg;
4484  struct cc_core_instance *core_instance = obj;
4485 
4486  ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name,
4487  cc_state_to_string(core_instance->current_state));
4488  AST_LIST_LOCK(core_instance->monitors);
4489  cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0);
4490  AST_LIST_UNLOCK(core_instance->monitors);
4491  return 0;
4492 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static const char * cc_state_to_string(enum cc_state state)
Definition: ccss.c:407
enum cc_state current_state
Definition: ccss.c:337
static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
Definition: ccss.c:4461
char device_name[1]
Definition: ccss.h:875
struct ast_cc_agent * agent
Definition: ccss.c:341

◆ request_cc()

static void request_cc ( struct cc_core_instance core_instance)
static

Definition at line 3108 of file ccss.c.

References cc_core_instance::agent, AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::available_timer_id, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_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().

3109 {
3110  struct ast_cc_monitor *monitor_iter;
3111  AST_LIST_LOCK(core_instance->monitors);
3112  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3113  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3114  if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) {
3116  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3117  monitor_iter->interface->device_name, 1);
3118  cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor");
3119  } else {
3120  cc_publish_requested(core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name);
3121  }
3122  }
3123  }
3125 
3126  if (!has_device_monitors(core_instance)) {
3127  ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC");
3128  }
3129  AST_LIST_UNLOCK(core_instance->monitors);
3130 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
struct ast_cc_monitor * next
Definition: ccss.h:562
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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:2050
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:551
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
unsigned int parent_id
Definition: ccss.h:524
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
static void cc_publish_requested(int core_id, const char *caller, const char *callee)
Definition: ccss.c:1087
int(* request_cc)(struct ast_cc_monitor *monitor, int *available_timer_id)
Request CCSS.
Definition: ccss.h:599
struct ast_cc_interface * interface
Definition: ccss.h:514
char device_name[1]
Definition: ccss.h:875
int available_timer_id
Definition: ccss.h:547
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:3093
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
struct ast_cc_agent * agent
Definition: ccss.c:341
char device_name[1]
Definition: ccss.h:839
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

◆ str_to_agent_policy()

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

Definition at line 698 of file ccss.c.

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

Referenced by ast_cc_set_param().

699 {
700  if (!strcasecmp(value, "never")) {
701  return AST_CC_AGENT_NEVER;
702  } else if (!strcasecmp(value, "native")) {
703  return AST_CC_AGENT_NATIVE;
704  } else if (!strcasecmp(value, "generic")) {
705  return AST_CC_AGENT_GENERIC;
706  } else {
707  ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value);
708  return AST_CC_AGENT_NEVER;
709  }
710 }
#define LOG_WARNING
Definition: logger.h:274
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42

◆ str_to_monitor_policy()

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

Definition at line 712 of file ccss.c.

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

Referenced by ast_cc_set_param().

713 {
714  if (!strcasecmp(value, "never")) {
715  return AST_CC_MONITOR_NEVER;
716  } else if (!strcasecmp(value, "native")) {
717  return AST_CC_MONITOR_NATIVE;
718  } else if (!strcasecmp(value, "generic")) {
719  return AST_CC_MONITOR_GENERIC;
720  } else if (!strcasecmp(value, "always")) {
721  return AST_CC_MONITOR_ALWAYS;
722  } else {
723  ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value);
724  return AST_CC_MONITOR_NEVER;
725  }
726 }
#define LOG_WARNING
Definition: logger.h:274
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42

◆ suspend()

static void suspend ( struct cc_core_instance core_instance)
static
Examples:
/usr/src/asterisk-18.5.0/main/app.c.

Definition at line 3193 of file ccss.c.

References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, 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 cc_caller_busy(), handle_bridge_technology_suspend(), and handle_controlstreamfile().

3194 {
3195  struct ast_cc_monitor *monitor_iter;
3196  AST_LIST_LOCK(core_instance->monitors);
3197  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3198  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3199  if (monitor_iter->callbacks->suspend(monitor_iter)) {
3201  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3202  monitor_iter->interface->device_name, 1);
3203  cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor");
3204  }
3205  }
3206  }
3208 
3209  if (!has_device_monitors(core_instance)) {
3210  ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC");
3211  }
3212  AST_LIST_UNLOCK(core_instance->monitors);
3213 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
struct ast_cc_monitor * next
Definition: ccss.h:562
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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:2050
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:551
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
unsigned int parent_id
Definition: ccss.h:524
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
struct ast_cc_interface * interface
Definition: ccss.h:514
int(* suspend)(struct ast_cc_monitor *monitor)
Suspend monitoring.
Definition: ccss.h:612
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:3093
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
char device_name[1]
Definition: ccss.h:839
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 4623 of file ccss.c.

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

Referenced by load_module().

4624 {
4625  ast_devstate_prov_del("ccss");
4632 
4633  if (cc_sched_context) {
4636  }
4637  if (cc_core_taskprocessor) {
4639  }
4640  /* Note that core instances must be destroyed prior to the generic_monitors */
4641  if (cc_core_instances) {
4642  ao2_t_ref(cc_core_instances, -1, "Unref cc_core_instances container in cc_shutdown");
4644  }
4645  if (generic_monitors) {
4646  ao2_t_ref(generic_monitors, -1, "Unref generic_monitor container in cc_shutdown");
4648  }
4649 
4650  return 0;
4651 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:418
static const char * ccreq_app
Definition: ccss.c:4255
#define NULL
Definition: resample.c:96
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static const char * CC_LOGGER_LEVEL_NAME
Definition: ccss.c:129
static struct ast_sched_context * cc_sched_context
Definition: ccss.c:115
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:2536
static struct ast_cli_entry cc_cli[]
Definition: ccss.c:4618
struct ao2_container * generic_monitors
Definition: ccss.c:1333
static struct ast_cc_agent_callbacks generic_agent_callbacks
Definition: ccss.c:2606
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:1254
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:1217
static struct ao2_container * cc_core_instances
Definition: ccss.c:327
static struct ast_cc_monitor_callbacks generic_monitor_cbs
Definition: ccss.c:1324
static const char * cccancel_app
Definition: ccss.c:4306
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:125

◆ unsuspend()

static void unsuspend ( struct cc_core_instance core_instance)
static

Definition at line 3146 of file ccss.c.

References AST_CC_DEVICE_MONITOR, ast_cc_failed(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_cc_monitor::callbacks, cc_extension_monitor_change_is_valid(), cc_unref(), cc_core_instance::core_id, 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().

3147 {
3148  struct ast_cc_monitor *monitor_iter;
3149  AST_LIST_LOCK(core_instance->monitors);
3150  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3151  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3152  if (monitor_iter->callbacks->unsuspend(monitor_iter)) {
3154  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3155  monitor_iter->interface->device_name, 1);
3156  cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor");
3157  }
3158  }
3159  }
3161 
3162  if (!has_device_monitors(core_instance)) {
3163  ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC");
3164  }
3165  AST_LIST_UNLOCK(core_instance->monitors);
3166 }
struct cc_monitor_tree * monitors
Definition: ccss.c:345
struct ast_cc_monitor * next
Definition: ccss.h:562
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3879
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:149
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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:2050
const struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:551
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
unsigned int parent_id
Definition: ccss.h:524
int(* unsuspend)(struct ast_cc_monitor *monitor)
Unsuspend monitoring.
Definition: ccss.h:640
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
struct ast_cc_interface * interface
Definition: ccss.h:514
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:3093
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
char device_name[1]
Definition: ccss.h:839
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:821

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CORE, }
static

Definition at line 4703 of file ccss.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4703 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_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: ccss.c:4511
static char * handle_cc_kill(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: ccss.c:4577

Definition at line 4618 of file ccss.c.

◆ cc_core_instances

struct ao2_container* cc_core_instances
static

Definition at line 327 of file ccss.c.

◆ CC_CORE_INSTANCES_BUCKETS

const int CC_CORE_INSTANCES_BUCKETS = 17
static

Definition at line 326 of file ccss.c.

Referenced by load_module().

◆ cc_core_taskprocessor

struct ast_taskprocessor* cc_core_taskprocessor
static

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

Definition at line 125 of file ccss.c.

◆ cc_default_params

const struct ast_cc_config_params cc_default_params
static

Definition at line 662 of file ccss.c.

Referenced by ast_cc_default_config_params().

◆ cc_logger_level

int cc_logger_level
static

◆ CC_LOGGER_LEVEL_NAME

const char* CC_LOGGER_LEVEL_NAME = "CC"
static

Name printed on all CC log messages.

Definition at line 129 of file ccss.c.

Referenced by load_module(), and unload_module().

◆ cc_monitor_backends

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

◆ cc_request_count

int cc_request_count
static

The current number of CC requests in the system

Definition at line 141 of file ccss.c.

Referenced by ast_cc_request_is_within_limits().

◆ cc_sched_context

struct ast_sched_context* cc_sched_context
static

The ast_sched_context used for all generic CC timeouts

Definition at line 115 of file ccss.c.

◆ cc_service_to_string_map

const { ... } cc_service_to_string_map[]

Referenced by cc_service_to_string().

◆ cc_state_to_devstate_map

enum ast_device_state cc_state_to_devstate_map[]
static

Definition at line 563 of file ccss.c.

◆ cc_state_to_string_map

const { ... } cc_state_to_string_map[]

Referenced by cc_state_to_string().

◆ cccancel_app

const char* cccancel_app = "CallCompletionCancel"
static

Definition at line 4306 of file ccss.c.

◆ ccreq_app

const char* ccreq_app = "CallCompletionRequest"
static

Definition at line 4255 of file ccss.c.

◆ core_id_counter

int core_id_counter
static

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

Definition at line 120 of file ccss.c.

Referenced by cc_interfaces_datastore_init().

◆ dialed_cc_interface_counter

int dialed_cc_interface_counter
static

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

Definition at line 1875 of file ccss.c.

◆ 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:1944
static void * dialed_cc_interfaces_duplicate(void *data)
Definition: ccss.c:1964

Definition at line 1989 of file ccss.c.

◆ generic_agent_callbacks

struct ast_cc_agent_callbacks generic_agent_callbacks
static

Definition at line 2606 of file ccss.c.

◆ generic_monitor_cbs

struct ast_cc_monitor_callbacks generic_monitor_cbs
static

Definition at line 1324 of file ccss.c.

◆ generic_monitors

struct ao2_container* generic_monitors

Definition at line 1333 of file ccss.c.

◆ global_cc_max_requests

unsigned int global_cc_max_requests
static

Parsed configuration value for cc_max_requests

Definition at line 137 of file ccss.c.

Referenced by ast_cc_request_is_within_limits(), and initialize_cc_max_requests().

◆ recall_ds_info

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

Definition at line 3399 of file ccss.c.

◆ service

enum ast_cc_service_type service

Definition at line 383 of file ccss.c.

Referenced by cc_build_payload(), cc_generic_monitor_request_cc(), and cc_service_to_string().

◆ service_string

const char* service_string

Definition at line 384 of file ccss.c.

◆ state

◆ state_change_funcs

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

Definition at line 3273 of file ccss.c.

Referenced by cc_do_state_change().

◆ state_string

const char* state_string

Definition at line 394 of file ccss.c.