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