Wed Jan 8 2020 09:49:58

Asterisk developer's documentation


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/event.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"

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...
 
struct  generic_tp_cb_data
 

Macros

#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 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 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_init (void)
 Initialize CCSS. 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...
 
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...
 
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...
 
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 extension as a starting point. 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 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 void cc_shutdown (void)
 
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 void check_callback_sanity (const struct ast_cc_agent_callbacks *callbacks)
 
static char * complete_core_id (const char *line, const char *word, int pos, int state)
 
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_list
create_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_pvt
extension_monitor_pvt_init (void)
 
static struct
ast_cc_agent_callbacks
find_agent_callbacks (struct ast_channel *chan)
 
static struct cc_core_instancefind_cc_core_instance (const int core_id)
 
static struct
generic_monitor_instance_list
find_generic_monitor_instance_list (const char *const device_name)
 
static struct
ast_cc_monitor_callbacks
find_monitor_callbacks (const char *const type)
 
static void generic_agent_devstate_cb (const struct ast_event *event, void *userdata)
 
static int generic_agent_devstate_unsubscribe (void *data)
 
static int generic_monitor_cmp_fn (void *obj, void *arg, int flags)
 
static void generic_monitor_devstate_cb (const struct ast_event *event, void *userdata)
 
static int generic_monitor_devstate_tp_cb (void *data)
 
static int generic_monitor_hash_fn (const void *obj, const int flags)
 
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_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 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 void unsuspend (struct cc_core_instance *core_instance)
 

Variables

struct cc_agent_backends cc_agent_backends = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
 
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 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 } , }
 
static int cc_request_count
 
static struct ast_sched_threadcc_sched_thread
 
struct {
   enum ast_cc_service_type   service
 
   const char *   service_string
 
cc_service_to_string_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 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 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

#define CC_MAX_AGENTS_DEFAULT   5

Definition at line 541 of file ccss.c.

#define CC_MAX_MONITORS_DEFAULT   5

Definition at line 542 of file ccss.c.

#define CC_OFFER_TIMER_DEFAULT   20 /* Seconds */

Definition at line 537 of file ccss.c.

#define CC_RECALL_TIMER_DEFAULT   20 /* Seconds */

Definition at line 540 of file ccss.c.

#define CCBS_AVAILABLE_TIMER_DEFAULT   4800 /* Seconds */

Definition at line 539 of file ccss.c.

#define CCNR_AVAILABLE_TIMER_DEFAULT   7200 /* Seconds */

Definition at line 538 of file ccss.c.

#define GLOBAL_CC_MAX_REQUESTS_DEFAULT   20

Definition at line 543 of file ccss.c.

Referenced by initialize_cc_max_requests().

Enumeration Type Documentation

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

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

Definition at line 459 of file ccss.c.

459  {
460  /* Only match agents that have not yet
461  * made a CC request
462  */
463  MATCH_NO_REQUEST = (1 << 0),
464  /* Only match agents that have made
465  * a CC request
466  */
467  MATCH_REQUEST = (1 << 1),
468 };

Function Documentation

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

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

564 {
565 #if defined(__AST_DEBUG_MALLOC)
566  struct ast_cc_config_params *params = __ast_malloc(sizeof(*params), file, line, function);
567 #else
568  struct ast_cc_config_params *params = ast_malloc(sizeof(*params));
569 #endif
570 
571  if (!params) {
572  return NULL;
573  }
574 
576  return params;
577 }
void * __ast_malloc(size_t size, const char *file, int lineno, const char *func)
void ast_cc_default_config_params(struct ast_cc_config_params *params)
Set the specified CC config params to default values.
Definition: ccss.c:558
#define ast_malloc(a)
Definition: astmm.h:91
static void agent_destroy ( void *  data)
static

Definition at line 2281 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().

2282 {
2283  struct ast_cc_agent *agent = data;
2284 
2285  if (agent->callbacks) {
2286  agent->callbacks->destructor(agent);
2287  }
2289 }
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:579
struct ast_cc_config_params * cc_params
Definition: ccss.h:842
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
void(* destructor)(struct ast_cc_agent *agent)
Destroy private data on the agent.
Definition: ccss.h:1055
static const char* agent_policy_to_str ( enum ast_cc_agent_policies  policy)
static

Definition at line 614 of file ccss.c.

References AST_CC_AGENT_GENERIC, AST_CC_AGENT_NATIVE, and AST_CC_AGENT_NEVER.

Referenced by ast_cc_get_param().

615 {
616  switch (policy) {
617  case AST_CC_AGENT_NEVER:
618  return "never";
619  case AST_CC_AGENT_NATIVE:
620  return "native";
622  return "generic";
623  default:
624  /* This should never happen... */
625  return "";
626  }
627 }
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 3510 of file ccss.c.

References CC_CALLER_REQUESTED, and cc_request_state_change().

Referenced by ccreq_exec(), handle_cc_subscribe(), and sig_pri_handle_cis_subcmds().

3511 {
3512  va_list ap;
3513  int res;
3514 
3515  va_start(ap, debug);
3517  va_end(ap);
3518  return res;
3519 }
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3062
unsigned int core_id
Definition: ccss.h:832
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 446 of file ccss.c.

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

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

447 {
448  struct cc_callback_helper helper = {.function = function, .args = args, .type = type};
449  struct cc_core_instance *core_instance;
450  if ((core_instance = ao2_t_callback(cc_core_instances, flags, cc_agent_callback_helper, &helper,
451  "Calling provided agent callback function"))) {
452  struct ast_cc_agent *agent = cc_ref(core_instance->agent, "An outside entity needs the agent");
453  cc_unref(core_instance, "agent callback done with the core_instance");
454  return agent;
455  }
456  return NULL;
457 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
ao2_callback_fn * function
Definition: ccss.c:429
static struct @350 args
#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:909
static const char type[]
Definition: chan_nbs.c:57
static int cc_agent_callback_helper(void *obj, void *args, int flags)
Definition: ccss.c:434
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
struct ast_cc_agent * agent
Definition: ccss.c:331
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 3554 of file ccss.c.

References CC_ACTIVE, and cc_request_state_change().

Referenced by cc_esc_publish_handler(), generic_agent_devstate_cb(), and sig_pri_handle_cis_subcmds().

3555 {
3556  va_list ap;
3557  int res;
3558 
3559  va_start(ap, debug);
3560  res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3561  va_end(ap);
3562  return res;
3563 }
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3062
unsigned int core_id
Definition: ccss.h:832
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 3543 of file ccss.c.

References CC_CALLER_BUSY, and cc_request_state_change().

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

3544 {
3545  va_list ap;
3546  int res;
3547 
3548  va_start(ap, debug);
3549  res = cc_request_state_change(CC_CALLER_BUSY, core_id, debug, ap);
3550  va_end(ap);
3551  return res;
3552 }
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3062
unsigned int core_id
Definition: ccss.h:832
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 3565 of file ccss.c.

References CC_RECALLING, and cc_request_state_change().

Referenced by generic_recall(), get_destination(), and sig_pri_handle_subcmds().

3566 {
3567  va_list ap;
3568  int res;
3569 
3570  va_start(ap, debug);
3571  res = cc_request_state_change(CC_RECALLING, core_id, debug, ap);
3572  va_end(ap);
3573  return res;
3574 }
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3062
unsigned int core_id
Definition: ccss.h:832
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 950 of file ccss.c.

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

Referenced by ast_cc_init(), and load_module().

951 {
952  struct cc_agent_backend *backend = ast_calloc(1, sizeof(*backend));
953 
954  if (!backend) {
955  return -1;
956  }
957 
958  backend->callbacks = callbacks;
962  return 0;
963 }
#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:944
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.c:945
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
#define ast_calloc(a, b)
Definition: astmm.h:82
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 3365 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_recall_ds_data::core_id, ast_datastore::data, cc_recall_ds_data::interface_tree, monitor, pbx_builtin_setvar_helper(), and str.

Referenced by generic_recall(), handle_request_invite(), and sig_pri_handle_subcmds().

3366 {
3367  struct ast_datastore *recall_datastore;
3368  struct cc_monitor_tree *interface_tree;
3369  struct ast_cc_monitor *monitor;
3370  struct cc_recall_ds_data *recall_data;
3371  struct ast_str *str = ast_str_create(64);
3372  int core_id;
3373 
3374  if (!str) {
3375  return -1;
3376  }
3377 
3378  ast_channel_lock(chan);
3379  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3380  ast_channel_unlock(chan);
3381  ast_free(str);
3382  return -1;
3383  }
3384  recall_data = recall_datastore->data;
3385  interface_tree = recall_data->interface_tree;
3386  core_id = recall_data->core_id;
3387  ast_channel_unlock(chan);
3388 
3389  AST_LIST_LOCK(interface_tree);
3390  monitor = AST_LIST_FIRST(interface_tree);
3391  build_cc_interfaces_chanvar(monitor, &str);
3392  AST_LIST_UNLOCK(interface_tree);
3393 
3394  pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3395  ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3396  core_id, ast_str_buffer(str));
3397 
3398  ast_free(str);
3399  return 0;
3400 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#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:497
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str **str)
Definition: ccss.c:3322
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
Structure for a data store object.
Definition: datastore.h:54
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:2604
const char * str
Definition: app_jack.c:144
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
static unsigned int monitor
Definition: chan_phone.c:108
The &quot;tree&quot; of interfaces that is dialed.
Definition: ccss.c:314
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_free(a)
Definition: astmm.h:97
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...
Definition: pbx.c:10546
void * data
Definition: datastore.h:56
static struct ast_datastore_info recall_ds_info
Definition: ccss.c:3133
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3109
static int cc_logger_level
Definition: ccss.c:124
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 3830 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(), sig_pri_handle_cis_subcmds(), and sip_cc_agent_status_request().

3831 {
3832  struct cc_status_response_args *args;
3833  struct cc_core_instance *core_instance;
3834  int res;
3835 
3836  args = ast_calloc(1, sizeof(*args));
3837  if (!args) {
3838  return -1;
3839  }
3840 
3841  core_instance = find_cc_core_instance(core_id);
3842  if (!core_instance) {
3843  ast_free(args);
3844  return -1;
3845  }
3846 
3847  args->core_instance = core_instance;
3848  args->devstate = devstate;
3849 
3851  if (res) {
3852  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3853  ast_free(args);
3854  }
3855  return res;
3856 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:421
static int cc_status_response(void *data)
Definition: ccss.c:3809
static struct @350 args
struct cc_core_instance * core_instance
Definition: ccss.c:3805
#define ast_free(a)
Definition: astmm.h:97
#define ast_calloc(a, b)
Definition: astmm.h:82
enum ast_device_state devstate
Definition: ccss.c:3806
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
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 965 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_monitor_backend::next.

Referenced by __unload_module(), cc_shutdown(), and unload_module().

966 {
967  struct cc_agent_backend *backend;
970  if (backend->callbacks == callbacks) {
972  ast_free(backend);
973  break;
974  }
975  }
978 }
#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:944
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:565
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.c:945
#define ast_free(a)
Definition: astmm.h:97
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
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 1239 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, ast_cc_monitor::interface, and monitor.

Referenced by cc_generic_monitor_request_cc(), and sip_cc_monitor_request_cc().

1240 {
1241  struct ast_cc_monitor *monitor = (struct ast_cc_monitor *) data;
1242  int res;
1243  monitor->available_timer_id = -1;
1244  res = ast_cc_monitor_failed(monitor->core_id, monitor->interface->device_name, "Available timer expired for monitor");
1245  cc_unref(monitor, "Unref reference from scheduler\n");
1246  return res;
1247 }
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:3678
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
int core_id
Definition: ccss.h:511
static unsigned int monitor
Definition: chan_phone.c:108
struct ast_cc_interface * interface
Definition: ccss.h:497
int available_timer_id
Definition: ccss.h:530
char device_name[1]
Definition: ccss.h:822
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 3913 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().

3917 {
3918  struct cc_control_payload *payload = ast_calloc(1, sizeof(*payload));
3919 
3920  if (!payload) {
3921  return -1;
3922  }
3923  if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, payload)) {
3924  /* Something screwed up, we can't make a frame with this */
3925  ast_free(payload);
3926  return -1;
3927  }
3928  frame->frametype = AST_FRAME_CONTROL;
3929  frame->subclass.integer = AST_CONTROL_CC;
3930  frame->data.ptr = payload;
3931  frame->datalen = sizeof(*payload);
3932  frame->mallocd = AST_MALLOCD_DATA;
3933  return 0;
3934 }
union ast_frame_subclass subclass
Definition: frame.h:146
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:212
void * private_data
Private data allocated by the callee.
Definition: ccss.c:247
void * ptr
Definition: frame.h:160
enum ast_cc_service_type service
Definition: chan_sip.c:821
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:3858
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:283
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:295
int datalen
Definition: frame.h:148
#define ast_free(a)
Definition: astmm.h:97
int mallocd
Definition: frame.h:152
#define ast_calloc(a, b)
Definition: astmm.h:82
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:230
enum ast_frame_type frametype
Definition: frame.h:144
union ast_frame::@172 data
#define AST_MALLOCD_DATA
Definition: frame.h:210
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 3969 of file ccss.c.

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

Referenced by dial_exec_full().

3971 {
3972  struct cc_control_payload payload;
3973  if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialstring, AST_CC_CCBS, private_data, &payload)) {
3974  /* Something screwed up. Don't try to handle this payload */
3976  return;
3977  }
3978  ast_handle_cc_control_frame(inbound, NULL, &payload);
3979 }
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:212
void * private_data
Private data allocated by the callee.
Definition: ccss.c:247
static void call_destructor_with_no_monitor(const char *const monitor_type, void *private_data)
Definition: ccss.c:1946
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:2048
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:3858
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:283
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:295
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:230
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 3936 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_NAME, ast_get_cc_monitor_policy(), ast_handle_cc_control_frame(), cc_build_payload(), and ast_channel::hangupcause.

Referenced by dial_exec_full().

3937 {
3939  struct cc_control_payload payload;
3940  struct ast_cc_config_params *cc_params;
3941 
3942  if (outgoing->hangupcause != AST_CAUSE_BUSY && outgoing->hangupcause != AST_CAUSE_CONGESTION) {
3943  /* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call
3944  * failing is something other than busy or congestion
3945  */
3946  return;
3947  }
3948 
3949  cc_params = ast_channel_get_cc_config_params(outgoing);
3950  if (!cc_params) {
3951  return;
3952  }
3954  /* This sort of CCBS only works if using generic CC. For native, we would end up sending
3955  * a CC request for a non-existent call. The far end will reject this every time
3956  */
3957  return;
3958  }
3959 
3960  ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
3961  if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
3962  dialstring, AST_CC_CCBS, NULL, &payload)) {
3963  /* Something screwed up, we can't make a frame with this */
3964  return;
3965  }
3966  ast_handle_cc_control_frame(incoming, outgoing, &payload);
3967 }
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:212
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:2048
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:3858
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:9754
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:763
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:283
#define AST_CC_GENERIC_MONITOR_TYPE
Definition: ccss.h:472
#define AST_CHANNEL_NAME
Definition: channel.h:137
#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:9776
int hangupcause
Definition: channel.h:849
#define AST_CAUSE_CONGESTION
Definition: causes.h:152
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 2146 of file ccss.c.

References AST_CC_AGENT_NEVER, ast_channel_datastore_find(), ast_channel_get_cc_config_params(), ast_channel_lock, 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_ref(), cc_unref(), ast_channel::context, ast_cc_monitor::core_id, dialed_cc_interfaces::core_id, ast_datastore::data, dialed_cc_interfaces::dial_parent_id, ast_channel::exten, ast_cc_monitor::id, dialed_cc_interfaces::ignore, dialed_cc_interfaces::interface_tree, ast_channel::macrocontext, ast_channel::macroexten, monitor, ast_channel::name, and S_OR.

Referenced by dial_exec_full().

2147 {
2148  /* There are three situations to deal with here:
2149  *
2150  * 1. The channel does not have a dialed_cc_interfaces datastore on
2151  * it. This means that this is the first time that Dial has
2152  * been called. We need to create/initialize the datastore.
2153  *
2154  * 2. The channel does have a cc_interface datastore on it and
2155  * the "ignore" indicator is 0. This means that a Local channel
2156  * was called by a "parent" dial. We can check the datastore's
2157  * parent field to see who the root of this particular dial tree
2158  * is.
2159  *
2160  * 3. The channel does have a cc_interface datastore on it and
2161  * the "ignore" indicator is 1. This means that a second Dial call
2162  * is being made from an extension. In this case, we do not
2163  * want to make any additions/modifications to the datastore. We
2164  * will instead set a flag to indicate that CCSS is completely
2165  * disabled for this Dial attempt.
2166  */
2167 
2168  struct ast_datastore *cc_interfaces_datastore;
2169  struct dialed_cc_interfaces *interfaces;
2170  struct ast_cc_monitor *monitor;
2171  struct ast_cc_config_params *cc_params;
2172 
2173  ast_channel_lock(chan);
2174 
2175  cc_params = ast_channel_get_cc_config_params(chan);
2176  if (!cc_params) {
2177  ast_channel_unlock(chan);
2178  return -1;
2179  }
2180  if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_NEVER) {
2181  /* We can't offer CC to this caller anyway, so don't bother with CC on this call
2182  */
2183  *ignore_cc = 1;
2184  ast_channel_unlock(chan);
2185  ast_log_dynamic_level(cc_logger_level, "Agent policy for %s is 'never'. CC not possible\n", chan->name);
2186  return 0;
2187  }
2188 
2189  if (!(cc_interfaces_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2190  /* Situation 1 has occurred */
2191  ast_channel_unlock(chan);
2192  return cc_interfaces_datastore_init(chan);
2193  }
2194  interfaces = cc_interfaces_datastore->data;
2195  ast_channel_unlock(chan);
2196 
2197  if (interfaces->ignore) {
2198  /* Situation 3 has occurred */
2199  *ignore_cc = 1;
2200  ast_log_dynamic_level(cc_logger_level, "Datastore is present with ignore flag set. Ignoring CC offers on this call\n");
2201  return 0;
2202  }
2203 
2204  /* Situation 2 has occurred */
2205  if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten),
2206  S_OR(chan->macrocontext, chan->context), interfaces->dial_parent_id))) {
2207  return -1;
2208  }
2209  monitor->core_id = interfaces->core_id;
2210  AST_LIST_LOCK(interfaces->interface_tree);
2211  cc_ref(monitor, "monitor tree's reference to the monitor");
2212  AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
2213  AST_LIST_UNLOCK(interfaces->interface_tree);
2214  interfaces->dial_parent_id = monitor->id;
2215  cc_unref(monitor, "Unref monitor's allocation reference");
2216  return 0;
2217 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
unsigned int id
Definition: ccss.h:502
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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:1819
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
Structure for a data store object.
Definition: datastore.h:54
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:2604
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:9754
int core_id
Definition: ccss.h:511
static struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1719
static int cc_interfaces_datastore_init(struct ast_channel *chan)
Definition: ccss.c:1868
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
static unsigned int monitor
Definition: chan_phone.c:108
const ast_string_field name
Definition: channel.h:787
#define ast_channel_unlock(chan)
Definition: channel.h:2467
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1659
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
void * data
Definition: datastore.h:56
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
unsigned int dial_parent_id
Definition: ccss.c:1632
static int cc_logger_level
Definition: ccss.c:124
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:746
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
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 3981 of file ccss.c.

References ast_get_channel_tech(), and ast_channel_tech::cc_callback.

Referenced by dial_exec_full().

3982 {
3983  const struct ast_channel_tech *chantech = ast_get_channel_tech(tech);
3984 
3985  if (chantech && chantech->cc_callback) {
3986  chantech->cc_callback(inbound, dest, callback);
3987  }
3988 
3989  return 0;
3990 }
struct ast_channel_tech * ast_get_channel_tech(const char *name)
Get a channel technology structure by name.
Definition: channel.c:960
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:635
Structure to describe a channel &quot;technology&quot;, ie a channel driver See for examples: ...
Definition: channel.h:507
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 3576 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, and cc_recall_ds_data::nested.

Referenced by wait_for_answer().

3577 {
3578  struct ast_datastore *recall_datastore;
3579  struct cc_recall_ds_data *recall_data;
3580  int core_id;
3581  va_list ap;
3582  int res;
3583 
3584  ast_channel_lock(chan);
3585  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3586  /* Silly! Why did you call this function if there's no recall DS? */
3587  ast_channel_unlock(chan);
3588  return -1;
3589  }
3590  recall_data = recall_datastore->data;
3591  if (recall_data->nested || recall_data->ignore) {
3592  /* If this is being called from a nested Dial, it is too
3593  * early to determine if the recall has actually completed.
3594  * The outermost dial is the only one with the authority to
3595  * declare the recall to be complete.
3596  *
3597  * Similarly, if this function has been called when the
3598  * recall has progressed beyond the first dial, this is not
3599  * a legitimate time to declare the recall to be done. In fact,
3600  * that should have been done already.
3601  */
3602  ast_channel_unlock(chan);
3603  return -1;
3604  }
3605  core_id = recall_data->core_id;
3606  ast_channel_unlock(chan);
3607  va_start(ap, debug);
3608  res = cc_request_state_change(CC_COMPLETE, core_id, debug, ap);
3609  va_end(ap);
3610  return res;
3611 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Structure for a data store object.
Definition: datastore.h:54
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:2604
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3062
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void * data
Definition: datastore.h:56
static struct ast_datastore_info recall_ds_info
Definition: ccss.c:3133
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 579 of file ccss.c.

References ast_free.

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

580 {
581  ast_free(params);
582 }
#define ast_free(a)
Definition: astmm.h:97
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 741 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().

742 {
743  *dest = *src;
744 }
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 558 of file ccss.c.

References cc_default_params.

Referenced by __ast_cc_config_params_init().

559 {
560  *params = cc_default_params;
561 }
static struct ast_cc_config_params cc_default_params
Definition: ccss.c:545
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 1735 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, extension_child_dialstring::original_dialstring, and ast_cc_monitor::private_data.

Referenced by dial_exec_full().

1736 {
1737  struct ast_datastore *cc_datastore;
1738  struct dialed_cc_interfaces *cc_interfaces;
1739  struct ast_cc_monitor *monitor;
1740  struct extension_monitor_pvt *extension_pvt;
1741  struct extension_child_dialstring *child_dialstring;
1742  struct cc_monitor_tree *interface_tree;
1743  int id;
1744 
1745  ast_channel_lock(incoming);
1746  if (!(cc_datastore = ast_channel_datastore_find(incoming, &dialed_cc_interfaces_info, NULL))) {
1747  ast_channel_unlock(incoming);
1748  return;
1749  }
1750 
1751  cc_interfaces = cc_datastore->data;
1752  interface_tree = cc_interfaces->interface_tree;
1753  id = cc_interfaces->dial_parent_id;
1754  ast_channel_unlock(incoming);
1755 
1756  AST_LIST_LOCK(interface_tree);
1757  AST_LIST_TRAVERSE(interface_tree, monitor, next) {
1758  if (monitor->id == id) {
1759  break;
1760  }
1761  }
1762 
1763  if (!monitor) {
1764  AST_LIST_UNLOCK(interface_tree);
1765  return;
1766  }
1767 
1768  extension_pvt = monitor->private_data;
1769  if (!(child_dialstring = ast_calloc(1, sizeof(*child_dialstring)))) {
1770  AST_LIST_UNLOCK(interface_tree);
1771  return;
1772  }
1773  ast_copy_string(child_dialstring->original_dialstring, dialstring, sizeof(child_dialstring->original_dialstring));
1774  ast_copy_string(child_dialstring->device_name, device_name, sizeof(child_dialstring->device_name));
1775  child_dialstring->is_valid = 1;
1776  AST_LIST_INSERT_TAIL(&extension_pvt->child_dialstrings, child_dialstring, next);
1777  AST_LIST_UNLOCK(interface_tree);
1778 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
unsigned int id
Definition: ccss.h:502
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition: ccss.c:1540
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Structure for a data store object.
Definition: datastore.h:54
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:2604
static struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1719
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
char device_name[AST_CHANNEL_NAME]
The name of the device being dialed.
Definition: ccss.c:1525
struct extension_monitor_pvt::@235 child_dialstrings
static unsigned int monitor
Definition: chan_phone.c:108
The &quot;tree&quot; of interfaces that is dialed.
Definition: ccss.c:314
#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:2467
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1659
void * data
Definition: datastore.h:56
char original_dialstring[AST_CHANNEL_NAME]
the original dialstring used to call a particular device
Definition: ccss.c:1506
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
Data regarding an extension monitor&#39;s child&#39;s dialstrings.
Definition: ccss.c:1490
Private data for an extension monitor.
Definition: ccss.c:1547
enum queue_result id
Definition: app_queue.c:1090
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:544
unsigned int dial_parent_id
Definition: ccss.c:1632
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 3613 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(), sig_pri_cc_agent_req_rsp(), sig_pri_cc_link_canceled(), sig_pri_handle_cis_subcmds(), sip_offer_timer_expire(), suspend(), unsuspend(), and wait_for_answer().

3614 {
3615  va_list ap;
3616  int res;
3617 
3618  va_start(ap, debug);
3619  res = cc_request_state_change(CC_FAILED, core_id, debug, ap);
3620  va_end(ap);
3621  return res;
3622 }
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3062
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 2224 of file ccss.c.

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

Referenced by sig_pri_cc_available(), sig_pri_cc_generic_check(), and sip_handle_cc().

2225 {
2226  struct ast_datastore *datastore;
2227  struct dialed_cc_interfaces *cc_interfaces;
2228  int core_id_return;
2229 
2230  ast_channel_lock(chan);
2231  if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
2232  ast_channel_unlock(chan);
2233  return -1;
2234  }
2235 
2236  cc_interfaces = datastore->data;
2237  core_id_return = cc_interfaces->ignore ? -1 : cc_interfaces->core_id;
2238  ast_channel_unlock(chan);
2239  return core_id_return;
2240 
2241 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Structure for a data store object.
Definition: datastore.h:54
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:2604
static struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1719
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void * data
Definition: datastore.h:56
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 3253 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, and cc_core_instance::monitors.

Referenced by sig_pri_call(), sig_pri_cc_generic_check(), and sip_call().

3254 {
3255  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3256  struct ast_cc_monitor *monitor_iter;
3257 
3258  if (!core_instance) {
3259  return NULL;
3260  }
3261 
3262  AST_LIST_LOCK(core_instance->monitors);
3263  AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
3264  if (!strcmp(monitor_iter->interface->device_name, device_name)) {
3265  /* Found a monitor. */
3266  cc_ref(monitor_iter, "Hand the requester of the monitor a reference");
3267  break;
3268  }
3269  }
3270  AST_LIST_UNLOCK(core_instance->monitors);
3271  cc_unref(core_instance, "Done with core instance ref in ast_cc_get_monitor_by_recall_core_id");
3272  return monitor_iter;
3273 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
struct ast_cc_monitor * next
Definition: ccss.h:545
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:421
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#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:497
char device_name[1]
Definition: ccss.h:822
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 645 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_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(), and value.

Referenced by acf_cc_read().

647 {
648  const char *value = NULL;
649 
650  if (!strcasecmp(name, "cc_callback_macro")) {
651  value = ast_get_cc_callback_macro(params);
652  } else if (!strcasecmp(name, "cc_agent_policy")) {
654  } else if (!strcasecmp(name, "cc_monitor_policy")) {
656  } else if (!strcasecmp(name, "cc_agent_dialstring")) {
657  value = ast_get_cc_agent_dialstring(params);
658  }
659  if (value) {
660  ast_copy_string(buf, value, buf_len);
661  return 0;
662  }
663 
664  /* The rest of these are all ints of some sort and require some
665  * snprintf-itude
666  */
667 
668  if (!strcasecmp(name, "cc_offer_timer")) {
669  snprintf(buf, buf_len, "%u", ast_get_cc_offer_timer(params));
670  } else if (!strcasecmp(name, "ccnr_available_timer")) {
671  snprintf(buf, buf_len, "%u", ast_get_ccnr_available_timer(params));
672  } else if (!strcasecmp(name, "ccbs_available_timer")) {
673  snprintf(buf, buf_len, "%u", ast_get_ccbs_available_timer(params));
674  } else if (!strcasecmp(name, "cc_max_agents")) {
675  snprintf(buf, buf_len, "%u", ast_get_cc_max_agents(params));
676  } else if (!strcasecmp(name, "cc_max_monitors")) {
677  snprintf(buf, buf_len, "%u", ast_get_cc_max_monitors(params));
678  } else if (!strcasecmp(name, "cc_recall_timer")) {
679  snprintf(buf, buf_len, "%u", ast_get_cc_recall_timer(params));
680  } else {
681  ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
682  return -1;
683  }
684 
685  return 0;
686 }
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition: ccss.c:864
#define LOG_WARNING
Definition: logger.h:144
unsigned int ast_get_cc_recall_timer(struct ast_cc_config_params *config)
Get the cc_recall_timer.
Definition: ccss.c:810
static const char * monitor_policy_to_str(enum ast_cc_monitor_policies policy)
Definition: ccss.c:629
int value
Definition: syslog.c:39
unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
Get the cc_max_agents.
Definition: ccss.c:854
enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config)
Get the cc_monitor_policy.
Definition: ccss.c:763
unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
Get the ccbs_available_timer.
Definition: ccss.c:825
unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
Get the ccnr_available_timer.
Definition: ccss.c:795
const char * ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
Get the cc_agent_dialstring.
Definition: ccss.c:840
const char * ast_get_cc_callback_macro(struct ast_cc_config_params *config)
Get the name of the callback_macro.
Definition: ccss.c:874
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static const char name[]
unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
Get the cc_offer_timer.
Definition: ccss.c:780
static const char * agent_policy_to_str(enum ast_cc_agent_policies policy)
Definition: ccss.c:614
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:746
int ast_cc_init ( void  )

Initialize CCSS.

Since
1.8 Performs startup routines necessary for CC operation.
Return values
0Success
nonzeroFailure

Definition at line 4340 of file ccss.c.

References ao2_t_container_alloc, ARRAY_LEN, ast_cc_agent_register(), ast_cc_monitor_register(), ast_cli_register_multiple(), ast_logger_register_level(), ast_register_application2(), ast_register_atexit(), ast_sched_thread_create(), ast_taskprocessor_get(), cc_core_instance_cmp_fn(), cc_core_instance_hash_fn(), cc_shutdown(), cccancel_exec(), ccreq_exec(), generic_monitor_cbs, generic_monitor_cmp_fn(), generic_monitor_hash_fn(), generic_monitors, initialize_cc_max_requests(), and TPS_REF_DEFAULT.

Referenced by main().

4341 {
4342  int res;
4343 
4346  "Create core instance container"))) {
4347  return -1;
4348  }
4351  "Create generic monitor container"))) {
4352  return -1;
4353  }
4355  return -1;
4356  }
4358  return -1;
4359  }
4360  res = ast_register_application2(ccreq_app, ccreq_exec, NULL, NULL, NULL);
4361  res |= ast_register_application2(cccancel_app, cccancel_exec, NULL, NULL, NULL);
4369  return res;
4370 }
int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks)
Register a set of agent callbacks with the core.
Definition: ccss.c:950
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
struct ast_sched_thread * ast_sched_thread_create(void)
Create a scheduler with a dedicated thread.
Definition: sched.c:167
static int dialed_cc_interface_counter
Definition: ccss.c:1605
static const int CC_CORE_INSTANCES_BUCKETS
Definition: ccss.c:316
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary...
static struct ast_sched_thread * cc_sched_thread
Definition: ccss.c:106
return a reference to a taskprocessor, create one if it does not exist
Definition: taskprocessor.h:58
static const char * ccreq_app
Definition: ccss.c:3992
#define ao2_t_container_alloc(arg1, arg2, arg3, arg4)
Allocate and initialize a container with the desired number of buckets.
Definition: astobj2.h:733
static const char * CC_LOGGER_LEVEL_NAME
Definition: ccss.c:120
static int generic_monitor_cmp_fn(void *obj, void *arg, int flags)
Definition: ccss.c:1100
int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
Register a set of monitor callbacks with the core.
Definition: ccss.c:895
static int cccancel_exec(struct ast_channel *chan, const char *data)
Definition: ccss.c:4045
static int generic_monitor_hash_fn(const void *obj, const int flags)
Definition: ccss.c:1094
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:998
static struct ast_cli_entry cc_cli[]
Definition: ccss.c:4308
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:1627
static int ccreq_exec(struct ast_channel *chan, const char *data)
Definition: ccss.c:3994
struct ao2_container * generic_monitors
Definition: ccss.c:1044
static struct ast_cc_agent_callbacks generic_agent_callbacks
Definition: ccss.c:2343
static int cc_core_instance_cmp_fn(void *obj, void *arg, int flags)
Definition: ccss.c:413
static void initialize_cc_max_requests(void)
Definition: ccss.c:4114
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition: pbx.c:6344
static struct ast_cc_monitor_callbacks generic_monitor_cbs
Definition: ccss.c:1035
static const char * cccancel_app
Definition: ccss.c:4043
static int cc_logger_level
Definition: ccss.c:124
static int cc_core_instance_hash_fn(const void *obj, const int flags)
Definition: ccss.c:407
static void cc_shutdown(void)
Definition: ccss.c:4313
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
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 727 of file ccss.c.

Referenced by build_peer(), and process_dahdi().

728 {
729  return (!strcasecmp(name, "cc_agent_policy") ||
730  !strcasecmp(name, "cc_monitor_policy") ||
731  !strcasecmp(name, "cc_offer_timer") ||
732  !strcasecmp(name, "ccnr_available_timer") ||
733  !strcasecmp(name, "ccbs_available_timer") ||
734  !strcasecmp(name, "cc_max_agents") ||
735  !strcasecmp(name, "cc_max_monitors") ||
736  !strcasecmp(name, "cc_callback_macro") ||
737  !strcasecmp(name, "cc_agent_dialstring") ||
738  !strcasecmp(name, "cc_recall_timer"));
739 }
static const char name[]
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 3172 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, and cc_recall_ds_data::nested.

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

3173 {
3174  struct ast_datastore *recall_datastore;
3175  struct cc_recall_ds_data *recall_data;
3176  struct cc_monitor_tree *interface_tree;
3177  char device_name[AST_CHANNEL_NAME];
3178  struct ast_cc_monitor *device_monitor;
3179  int core_id_candidate;
3180 
3181  ast_assert(core_id != NULL);
3182 
3183  *core_id = -1;
3184 
3185  ast_channel_lock(chan);
3186  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3187  /* Obviously not a recall if the datastore isn't present */
3188  ast_channel_unlock(chan);
3189  return 0;
3190  }
3191 
3192  recall_data = recall_datastore->data;
3193 
3194  if (recall_data->ignore) {
3195  /* Though this is a recall, the call to this particular interface is not part of the
3196  * recall either because this is a call forward or because this is not the first
3197  * invocation of Dial during this call
3198  */
3199  ast_channel_unlock(chan);
3200  return 0;
3201  }
3202 
3203  if (!recall_data->nested) {
3204  /* If the nested flag is not set, then this means that
3205  * the channel passed to this function is the caller making
3206  * the recall. This means that we shouldn't look through
3207  * the monitor tree for the channel because it shouldn't be
3208  * there. However, this is a recall though, so return true.
3209  */
3210  *core_id = recall_data->core_id;
3211  ast_channel_unlock(chan);
3212  return 1;
3213  }
3214 
3215  if (ast_strlen_zero(monitor_type)) {
3216  /* If someone passed a NULL or empty monitor type, then it is clear
3217  * the channel they passed in was an incoming channel, and so searching
3218  * the list of dialed interfaces is not going to be helpful. Just return
3219  * false immediately.
3220  */
3221  ast_channel_unlock(chan);
3222  return 0;
3223  }
3224 
3225  interface_tree = recall_data->interface_tree;
3226  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
3227  /* We grab the value of the recall_data->core_id so that we
3228  * can unlock the channel before we start looking through the
3229  * interface list. That way we don't have to worry about a possible
3230  * clash between the channel lock and the monitor tree lock.
3231  */
3232  core_id_candidate = recall_data->core_id;
3233  ast_channel_unlock(chan);
3234 
3235  /*
3236  * Now we need to find out if the channel device name
3237  * is in the list of interfaces in the called tree.
3238  */
3239  AST_LIST_LOCK(interface_tree);
3240  AST_LIST_TRAVERSE(interface_tree, device_monitor, next) {
3241  if (!strcmp(device_monitor->interface->device_name, device_name) &&
3242  !strcmp(device_monitor->interface->monitor_type, monitor_type)) {
3243  /* BOOM! Device is in the tree! We have a winner! */
3244  *core_id = core_id_candidate;
3245  AST_LIST_UNLOCK(interface_tree);
3246  return 1;
3247  }
3248  }
3249  AST_LIST_UNLOCK(interface_tree);
3250  return 0;
3251 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
struct ast_cc_monitor * next
Definition: ccss.h:545
#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
#define ast_assert(a)
Definition: utils.h:738
Structure for a data store object.
Definition: datastore.h:54
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:2604
int core_id
Definition: ccss.h:511
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
The &quot;tree&quot; of interfaces that is dialed.
Definition: ccss.c:314
#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:2467
#define AST_CHANNEL_NAME
Definition: channel.h:137
const char * monitor_type
The type of monitor that should be used for this interface.
Definition: ccss.h:813
struct ast_cc_interface * interface
Definition: ccss.h:497
void * data
Definition: datastore.h:56
static struct ast_datastore_info recall_ds_info
Definition: ccss.c:3133
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:9776
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3109
char device_name[1]
Definition: ccss.h:822
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.
Parameters
core_idThe core ID of the corresponding CC transaction
debug
Return values
0Request successfully queued
-1Request could not be queued

Definition at line 3532 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(), handle_cc_notify(), and sig_pri_handle_cis_subcmds().

3533 {
3534  va_list ap;
3535  int res;
3536 
3537  va_start(ap, debug);
3538  res = cc_request_state_change(CC_CALLEE_READY, core_id, debug, ap);
3539  va_end(ap);
3540  return res;
3541 }
int core_id
Definition: ccss.h:511
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3062
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 4105 of file ccss.c.

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

4106 {
4107  struct count_monitors_cb_data data = {.device_name = name, .monitor_type = type,};
4108 
4109  ao2_t_callback(cc_core_instances, OBJ_NODATA, count_monitors_cb, &data, "Counting agents");
4110  ast_log_dynamic_level(cc_logger_level, "Counted %d monitors\n", data.count);
4111  return data.count;
4112 }
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
static int count_monitors_cb(void *obj, void *arg, int flags)
Definition: ccss.c:4085
#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:909
static const char name[]
static const char type[]
Definition: chan_nbs.c:57
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
static int cc_logger_level
Definition: ccss.c:124
const char * device_name
Definition: ccss.c:4080
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 3678 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(), handle_response_subscribe(), sig_pri_cc_link_canceled(), and sig_pri_handle_cis_subcmds().

3679 {
3680  struct ast_cc_monitor_failure_data *failure_data;
3681  int res;
3682  va_list ap;
3683 
3684  if (!(failure_data = ast_calloc(1, sizeof(*failure_data)))) {
3685  return -1;
3686  }
3687 
3688  if (!(failure_data->device_name = ast_strdup(monitor_name))) {
3689  ast_free(failure_data);
3690  return -1;
3691  }
3692 
3693  va_start(ap, debug);
3694  if (ast_vasprintf(&failure_data->debug, debug, ap) == -1) {
3695  va_end(ap);
3696  ast_free((char *)failure_data->device_name);
3697  ast_free(failure_data);
3698  return -1;
3699  }
3700  va_end(ap);
3701 
3702  failure_data->core_id = core_id;
3703 
3705  if (res) {
3706  ast_free((char *)failure_data->device_name);
3707  ast_free((char *)failure_data->debug);
3708  ast_free(failure_data);
3709  }
3710  return res;
3711 }
#define ast_strdup(a)
Definition: astmm.h:109
#define ast_vasprintf(a, b, c)
Definition: astmm.h:127
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
const char * device_name
Definition: ccss.c:3625
static int cc_monitor_failed(void *data)
Definition: ccss.c:3630
#define ast_free(a)
Definition: astmm.h:97
#define ast_calloc(a, b)
Definition: astmm.h:82
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
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 3788 of file ccss.c.

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

Referenced by sig_pri_handle_cis_subcmds().

3789 {
3790  int res;
3791  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3792 
3793  if (!core_instance) {
3794  return -1;
3795  }
3796 
3798  if (res) {
3799  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3800  }
3801  return res;
3802 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:421
static int cc_party_b_free(void *data)
Definition: ccss.c:3776
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
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 895 of file ccss.c.

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

Referenced by ast_cc_init(), and load_module().

896 {
897  struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend));
898 
899  if (!backend) {
900  return -1;
901  }
902 
903  backend->callbacks = callbacks;
904 
908  return 0;
909 }
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.c:890
#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_monitor_backend * next
Definition: ccss.c:889
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
#define ast_calloc(a, b)
Definition: astmm.h:82
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 3521 of file ccss.c.

References CC_ACTIVE, and cc_request_state_change().

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

3522 {
3523  va_list ap;
3524  int res;
3525 
3526  va_start(ap, debug);
3527  res = cc_request_state_change(CC_ACTIVE, core_id, debug, ap);
3528  va_end(ap);
3529  return res;
3530 }
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3062
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 3723 of file ccss.c.

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

Referenced by sig_pri_handle_cis_subcmds().

3724 {
3725  int res;
3726  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3727 
3728  if (!core_instance) {
3729  return -1;
3730  }
3731 
3733  if (res) {
3734  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3735  }
3736  return res;
3737 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:421
static int cc_status_request(void *data)
Definition: ccss.c:3713
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
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 3760 of file ccss.c.

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

Referenced by sig_pri_handle_cis_subcmds().

3761 {
3762  int res;
3763  struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
3764 
3765  if (!core_instance) {
3766  return -1;
3767  }
3768 
3770  if (res) {
3771  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3772  }
3773  return res;
3774 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:421
static int cc_stop_ringing(void *data)
Definition: ccss.c:3739
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
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 928 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(), cc_shutdown(), and unload_module().

929 {
930  struct cc_monitor_backend *backend;
933  if (backend->callbacks == callbacks) {
935  ast_free(backend);
936  break;
937  }
938  }
941 }
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.c:890
#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
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:565
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
#define ast_free(a)
Definition: astmm.h:97
struct cc_monitor_backend * next
Definition: ccss.c:889
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
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 3485 of file ccss.c.

References ast_channel_datastore_find(), ast_channel_lock, 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 ast_channel::name.

Referenced by ast_hangup().

3486 {
3487  int core_id;
3488  int res = -1;
3489  struct ast_datastore *datastore;
3490  struct dialed_cc_interfaces *cc_interfaces;
3491  char cc_is_offerable;
3492 
3493  ast_channel_lock(caller_chan);
3494  if (!(datastore = ast_channel_datastore_find(caller_chan, &dialed_cc_interfaces_info, NULL))) {
3495  ast_channel_unlock(caller_chan);
3496  return res;
3497  }
3498 
3499  cc_interfaces = datastore->data;
3500  cc_is_offerable = cc_interfaces->is_original_caller;
3501  core_id = cc_interfaces->core_id;
3502  ast_channel_unlock(caller_chan);
3503 
3504  if (cc_is_offerable) {
3505  res = cc_offer(core_id, "CC offered to caller %s", caller_chan->name);
3506  }
3507  return res;
3508 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Structure for a data store object.
Definition: datastore.h:54
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:2604
char is_original_caller
Definition: ccss.c:1655
static struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1719
const ast_string_field name
Definition: channel.h:787
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static int cc_offer(const int core_id, const char *const debug,...)
Definition: ccss.c:3474
void * data
Definition: datastore.h:56
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 2219 of file ccss.c.

References global_cc_max_requests.

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

2220 {
2222 }
static unsigned int global_cc_max_requests
Definition: ccss.c:128
static int cc_request_count
Definition: ccss.c:132
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 688 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_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().

690 {
691  unsigned int value_as_uint;
692  if (!strcasecmp(name, "cc_agent_policy")) {
694  } else if (!strcasecmp(name, "cc_monitor_policy")) {
696  } else if (!strcasecmp(name, "cc_agent_dialstring")) {
698  } else if (!strcasecmp(name, "cc_callback_macro")) {
700  return 0;
701  }
702 
703  if (!sscanf(value, "%30u", &value_as_uint) == 1) {
704  return -1;
705  }
706 
707  if (!strcasecmp(name, "cc_offer_timer")) {
708  ast_set_cc_offer_timer(params, value_as_uint);
709  } else if (!strcasecmp(name, "ccnr_available_timer")) {
710  ast_set_ccnr_available_timer(params, value_as_uint);
711  } else if (!strcasecmp(name, "ccbs_available_timer")) {
712  ast_set_ccbs_available_timer(params, value_as_uint);
713  } else if (!strcasecmp(name, "cc_max_agents")) {
714  ast_set_cc_max_agents(params, value_as_uint);
715  } else if (!strcasecmp(name, "cc_max_monitors")) {
716  ast_set_cc_max_monitors(params, value_as_uint);
717  } else if (!strcasecmp(name, "cc_recall_timer")) {
718  ast_set_cc_recall_timer(params, value_as_uint);
719  } else {
720  ast_log(LOG_WARNING, "%s is not a valid CC parameter. Ignoring.\n", name);
721  return -1;
722  }
723 
724  return 0;
725 }
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:751
static enum ast_cc_monitor_policies str_to_monitor_policy(const char *const value)
Definition: ccss.c:598
#define LOG_WARNING
Definition: logger.h:144
void ast_set_cc_max_monitors(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_monitors.
Definition: ccss.c:869
void ast_set_ccnr_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccnr_available_timer.
Definition: ccss.c:800
int value
Definition: syslog.c:39
void ast_set_cc_offer_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_offer_timer.
Definition: ccss.c:785
void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char *const value)
Set the callback_macro name.
Definition: ccss.c:879
static enum ast_cc_agent_policies str_to_agent_policy(const char *const value)
Definition: ccss.c:584
void ast_set_cc_recall_timer(struct ast_cc_config_params *config, unsigned int value)
Set the cc_recall_timer.
Definition: ccss.c:815
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static const char name[]
void ast_set_ccbs_available_timer(struct ast_cc_config_params *config, unsigned int value)
Set the ccbs_available_timer.
Definition: ccss.c:830
void ast_set_cc_max_agents(struct ast_cc_config_params *config, unsigned int value)
Set the cc_max_agents.
Definition: ccss.c:859
void ast_set_cc_agent_dialstring(struct ast_cc_config_params *config, const char *const value)
Set the cc_agent_dialstring.
Definition: ccss.c:845
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:768
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 840 of file ccss.c.

References ast_cc_config_params::cc_agent_dialstring.

Referenced by ast_cc_get_param().

841 {
842  return config->cc_agent_dialstring;
843 }
char cc_agent_dialstring[AST_MAX_EXTENSION]
Definition: ccss.c:162
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 746 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().

747 {
748  return config->cc_agent_policy;
749 }
enum ast_cc_agent_policies cc_agent_policy
Definition: ccss.c:153
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 874 of file ccss.c.

References ast_cc_config_params::cc_callback_macro.

Referenced by ast_cc_get_param(), and generic_recall().

875 {
876  return config->cc_callback_macro;
877 }
char cc_callback_macro[AST_MAX_EXTENSION]
Definition: ccss.c:161
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 854 of file ccss.c.

References ast_cc_config_params::cc_max_agents.

Referenced by ast_cc_get_param(), and cc_core_init_instance().

855 {
856  return config->cc_max_agents;
857 }
unsigned int cc_max_agents
Definition: ccss.c:159
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 864 of file ccss.c.

References ast_cc_config_params::cc_max_monitors.

Referenced by ast_cc_get_param(), and ast_queue_cc_frame().

865 {
866  return config->cc_max_monitors;
867 }
unsigned int cc_max_monitors
Definition: ccss.c:160
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 763 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(), sig_pri_cc_available(), sig_pri_cc_generic_check(), and sip_handle_cc().

764 {
765  return config->cc_monitor_policy;
766 }
enum ast_cc_monitor_policies cc_monitor_policy
Definition: ccss.c:154
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 780 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().

781 {
782  return config->cc_offer_timer;
783 }
unsigned int cc_offer_timer
Definition: ccss.c:155
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 810 of file ccss.c.

References ast_cc_config_params::cc_recall_timer.

Referenced by ast_cc_get_param(), and generic_recall().

811 {
812  return config->cc_recall_timer;
813 }
unsigned int cc_recall_timer
Definition: ccss.c:158
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 825 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().

826 {
827  return config->ccbs_available_timer;
828 }
unsigned int ccbs_available_timer
Definition: ccss.c:157
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 795 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().

796 {
797  return config->ccnr_available_timer;
798 }
unsigned int ccnr_available_timer
Definition: ccss.c:156
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 2048 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_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, EVENT_FLAG_CC, 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, manager_event, monitor, cc_control_payload::monitor_type, 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().

2049 {
2050  char *device_name;
2051  char *dialstring;
2052  struct ast_cc_monitor *monitor;
2053  struct ast_datastore *cc_datastore;
2054  struct dialed_cc_interfaces *cc_interfaces;
2055  struct cc_control_payload *cc_data = frame_data;
2056  struct cc_core_instance *core_instance;
2057 
2058  device_name = cc_data->device_name;
2059  dialstring = cc_data->dialstring;
2060 
2061  ast_channel_lock(inbound);
2062  if (!(cc_datastore = ast_channel_datastore_find(inbound, &dialed_cc_interfaces_info, NULL))) {
2063  ast_log(LOG_WARNING, "Unable to retrieve CC datastore while processing CC frame from '%s'. CC services will be unavailable.\n", device_name);
2064  ast_channel_unlock(inbound);
2066  return;
2067  }
2068 
2069  cc_interfaces = cc_datastore->data;
2070 
2071  if (cc_interfaces->ignore) {
2072  ast_channel_unlock(inbound);
2074  return;
2075  }
2076 
2077  if (!cc_interfaces->is_original_caller) {
2078  /* If the is_original_caller is not set on the *inbound* channel, then
2079  * it must be a local channel. As such, we do not want to create a core instance
2080  * or an agent for the local channel. Instead, we want to pass this along to the
2081  * other side of the local channel so that the original caller can benefit.
2082  */
2083  ast_channel_unlock(inbound);
2084  ast_indicate_data(inbound, AST_CONTROL_CC, cc_data, sizeof(*cc_data));
2085  return;
2086  }
2087 
2088  core_instance = find_cc_core_instance(cc_interfaces->core_id);
2089  if (!core_instance) {
2090  core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree,
2091  cc_interfaces->core_id, cc_data);
2092  if (!core_instance) {
2093  cc_interfaces->ignore = 1;
2094  ast_channel_unlock(inbound);
2096  return;
2097  }
2098  }
2099 
2100  ast_channel_unlock(inbound);
2101 
2102  /* Yeah this kind of sucks, but luckily most people
2103  * aren't dialing thousands of interfaces on every call
2104  *
2105  * This traversal helps us to not create duplicate monitors in
2106  * case a device queues multiple CC control frames.
2107  */
2108  AST_LIST_LOCK(cc_interfaces->interface_tree);
2109  AST_LIST_TRAVERSE(cc_interfaces->interface_tree, monitor, next) {
2110  if (!strcmp(monitor->interface->device_name, device_name)) {
2111  ast_log_dynamic_level(cc_logger_level, "Core %d: Device %s sent us multiple CC control frames. Ignoring those beyond the first.\n",
2112  core_instance->core_id, device_name);
2113  AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2114  cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2116  return;
2117  }
2118  }
2119  AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2120 
2121  if (!(monitor = cc_device_monitor_init(device_name, dialstring, cc_data, core_instance->core_id))) {
2122  ast_log(LOG_WARNING, "Unable to create CC device interface for '%s'. CC services will be unavailable on this interface.\n", device_name);
2123  cc_unref(core_instance, "Returning early from ast_handle_cc_control_frame. Unref core_instance");
2125  return;
2126  }
2127 
2128  AST_LIST_LOCK(cc_interfaces->interface_tree);
2129  cc_ref(monitor, "monitor tree's reference to the monitor");
2130  AST_LIST_INSERT_TAIL(cc_interfaces->interface_tree, monitor, next);
2131  AST_LIST_UNLOCK(cc_interfaces->interface_tree);
2132 
2133  cc_extension_monitor_change_is_valid(core_instance, monitor->parent_id, monitor->interface->device_name, 0);
2134 
2135  manager_event(EVENT_FLAG_CC, "CCAvailable",
2136  "CoreID: %d\r\n"
2137  "Callee: %s\r\n"
2138  "Service: %s\r\n",
2139  cc_interfaces->core_id, device_name, cc_service_to_string(cc_data->service)
2140  );
2141 
2142  cc_unref(core_instance, "Done with core_instance after handling CC control frame");
2143  cc_unref(monitor, "Unref reference from allocating monitor");
2144 }
static const char * cc_service_to_string(enum ast_cc_service_type service)
Definition: ccss.c:402
#define ast_channel_lock(chan)
Definition: channel.h:2466
The payload for an AST_CONTROL_CC frame.
Definition: ccss.c:212
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
void * private_data
Private data allocated by the callee.
Definition: ccss.c:247
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:421
#define LOG_WARNING
Definition: logger.h:144
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void call_destructor_with_no_monitor(const char *const monitor_type, void *private_data)
Definition: ccss.c:1946
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:4447
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
Structure for a data store object.
Definition: datastore.h:54
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:1780
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:2604
#define EVENT_FLAG_CC
Definition: manager.h:86
unsigned int parent_id
Definition: ccss.h:507
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:1982
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:2652
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:283
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:295
char is_original_caller
Definition: ccss.c:1655
static struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1719
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
static unsigned int monitor
Definition: chan_phone.c:108
enum ast_cc_service_type service
Service offered by the endpoint.
Definition: ccss.c:256
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#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:2467
struct ast_cc_interface * interface
Definition: ccss.h:497
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1659
void * data
Definition: datastore.h:56
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:230
char device_name[1]
Definition: ccss.h:822
static int cc_logger_level
Definition: ccss.c:124
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
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 3454 of file ccss.c.

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

Referenced by dial_exec_full(), and do_forward().

3455 {
3456  struct ast_datastore *cc_datastore;
3457  struct ast_datastore *cc_recall_datastore;
3458  struct dialed_cc_interfaces *cc_interfaces;
3459  struct cc_recall_ds_data *recall_cc_data;
3460 
3461  ast_channel_lock(chan);
3462  if ((cc_datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
3463  cc_interfaces = cc_datastore->data;
3464  cc_interfaces->ignore = 1;
3465  }
3466 
3467  if ((cc_recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3468  recall_cc_data = cc_recall_datastore->data;
3469  recall_cc_data->ignore = 1;
3470  }
3471  ast_channel_unlock(chan);
3472 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Structure for a data store object.
Definition: datastore.h:54
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:2604
static struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1719
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void * data
Definition: datastore.h:56
static struct ast_datastore_info recall_ds_info
Definition: ccss.c:3133
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 3886 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(), and LOG_NOTICE.

Referenced by analog_call(), sig_pri_cc_available(), sig_pri_cc_generic_check(), and sip_handle_cc().

3888 {
3889  struct ast_frame frame = {0,};
3890  char device_name[AST_CHANNEL_NAME];
3891  int retval;
3892  struct ast_cc_config_params *cc_params;
3893 
3894  cc_params = ast_channel_get_cc_config_params(chan);
3895  if (!cc_params) {
3896  return -1;
3897  }
3898  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
3899  if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
3900  ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
3901  return -1;
3902  }
3903 
3904  if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialstring, service, private_data, &frame)) {
3905  /* Frame building failed. We can't use this. */
3906  return -1;
3907  }
3908  retval = ast_queue_frame(chan, &frame);
3909  ast_frfree(&frame);
3910  return retval;
3911 }
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:4105
unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config)
Get the cc_max_monitors.
Definition: ccss.c:864
enum ast_cc_service_type service
Definition: chan_sip.c:821
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:9754
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:3913
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:1558
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define AST_CHANNEL_NAME
Definition: channel.h:137
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:9776
Data structure associated with a single frame of data.
Definition: frame.h:142
#define ast_frfree(fr)
Definition: frame.h:583
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 845 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().

846 {
847  if (ast_strlen_zero(value)) {
848  config->cc_agent_dialstring[0] = '\0';
849  } else {
851  }
852 }
int value
Definition: syslog.c:39
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char cc_agent_dialstring[AST_MAX_EXTENSION]
Definition: ccss.c:162
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 751 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().

752 {
753  /* Screw C and its weak type checking for making me have to do this
754  * validation at runtime.
755  */
756  if (value < AST_CC_AGENT_NEVER || value > AST_CC_AGENT_GENERIC) {
757  return -1;
758  }
759  config->cc_agent_policy = value;
760  return 0;
761 }
enum ast_cc_agent_policies cc_agent_policy
Definition: ccss.c:153
int value
Definition: syslog.c:39
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 879 of file ccss.c.

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

Referenced by ast_cc_set_param().

880 {
881  if (ast_strlen_zero(value)) {
882  config->cc_callback_macro[0] = '\0';
883  } else {
884  ast_copy_string(config->cc_callback_macro, value, sizeof(config->cc_callback_macro));
885  }
886 }
int value
Definition: syslog.c:39
char cc_callback_macro[AST_MAX_EXTENSION]
Definition: ccss.c:161
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
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 extension as a starting point.

Since
1.8

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 chan_local, 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 3402 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_recall_ds_data::core_id, ast_datastore::data, ast_cc_interface::device_name, ast_cc_monitor::interface, cc_recall_ds_data::interface_tree, pbx_builtin_setvar_helper(), and str.

Referenced by local_call().

3403 {
3404  struct ast_datastore *recall_datastore;
3405  struct cc_monitor_tree *interface_tree;
3406  struct ast_cc_monitor *monitor_iter;
3407  struct cc_recall_ds_data *recall_data;
3408  struct ast_str *str = ast_str_create(64);
3409  int core_id;
3410 
3411  if (!str) {
3412  return -1;
3413  }
3414 
3415  ast_channel_lock(chan);
3416  if (!(recall_datastore = ast_channel_datastore_find(chan, &recall_ds_info, NULL))) {
3417  ast_channel_unlock(chan);
3418  ast_free(str);
3419  return -1;
3420  }
3421  recall_data = recall_datastore->data;
3422  interface_tree = recall_data->interface_tree;
3423  core_id = recall_data->core_id;
3424  ast_channel_unlock(chan);
3425 
3426  AST_LIST_LOCK(interface_tree);
3427  AST_LIST_TRAVERSE(interface_tree, monitor_iter, next) {
3428  if (!strcmp(monitor_iter->interface->device_name, extension)) {
3429  break;
3430  }
3431  }
3432 
3433  if (!monitor_iter) {
3434  /* We couldn't find this extension. This may be because
3435  * we have been directed into an unexpected extension because
3436  * the admin has changed a CC_INTERFACES variable at some point.
3437  */
3438  AST_LIST_UNLOCK(interface_tree);
3439  ast_free(str);
3440  return -1;
3441  }
3442 
3443  build_cc_interfaces_chanvar(monitor_iter, &str);
3444  AST_LIST_UNLOCK(interface_tree);
3445 
3446  pbx_builtin_setvar_helper(chan, "CC_INTERFACES", ast_str_buffer(str));
3447  ast_log_dynamic_level(cc_logger_level, "Core %d: CC_INTERFACES set to %s\n",
3448  core_id, ast_str_buffer(str));
3449 
3450  ast_free(str);
3451  return 0;
3452 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#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:497
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
static void build_cc_interfaces_chanvar(struct ast_cc_monitor *starting_point, struct ast_str **str)
Definition: ccss.c:3322
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
Structure for a data store object.
Definition: datastore.h:54
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:2604
const char * str
Definition: app_jack.c:144
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
The &quot;tree&quot; of interfaces that is dialed.
Definition: ccss.c:314
#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:2467
#define ast_free(a)
Definition: astmm.h:97
struct ast_cc_interface * interface
Definition: ccss.h:497
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...
Definition: pbx.c:10546
void * data
Definition: datastore.h:56
static struct ast_datastore_info recall_ds_info
Definition: ccss.c:3133
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3109
char device_name[1]
Definition: ccss.h:822
static int cc_logger_level
Definition: ccss.c:124
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 859 of file ccss.c.

References ast_cc_config_params::cc_max_agents, and value.

Referenced by ast_cc_set_param().

860 {
861  config->cc_max_agents = value;
862 }
int value
Definition: syslog.c:39
unsigned int cc_max_agents
Definition: ccss.c:159
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 869 of file ccss.c.

References ast_cc_config_params::cc_max_monitors, and value.

Referenced by ast_cc_set_param().

870 {
871  config->cc_max_monitors = value;
872 }
int value
Definition: syslog.c:39
unsigned int cc_max_monitors
Definition: ccss.c:160
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 768 of file ccss.c.

References AST_CC_MONITOR_ALWAYS, ast_cc_config_params::cc_monitor_policy, and value.

Referenced by ast_cc_set_param().

769 {
770  /* Screw C and its weak type checking for making me have to do this
771  * validation at runtime.
772  */
773  if (value < AST_CC_MONITOR_NEVER || value > AST_CC_MONITOR_ALWAYS) {
774  return -1;
775  }
776  config->cc_monitor_policy = value;
777  return 0;
778 }
int value
Definition: syslog.c:39
enum ast_cc_monitor_policies cc_monitor_policy
Definition: ccss.c:154
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 785 of file ccss.c.

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

Referenced by ast_cc_set_param().

786 {
787  /* 0 is an unreasonable value for any timer. Stick with the default */
788  if (value == 0) {
789  ast_log(LOG_WARNING, "0 is an invalid value for cc_offer_timer. Retaining value as %u\n", config->cc_offer_timer);
790  return;
791  }
792  config->cc_offer_timer = value;
793 }
#define LOG_WARNING
Definition: logger.h:144
int value
Definition: syslog.c:39
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned int cc_offer_timer
Definition: ccss.c:155
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 815 of file ccss.c.

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

Referenced by ast_cc_set_param().

816 {
817  /* 0 is an unreasonable value for any timer. Stick with the default */
818  if (value == 0) {
819  ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->cc_recall_timer);
820  return;
821  }
822  config->cc_recall_timer = value;
823 }
#define LOG_WARNING
Definition: logger.h:144
unsigned int cc_recall_timer
Definition: ccss.c:158
int value
Definition: syslog.c:39
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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 830 of file ccss.c.

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

Referenced by ast_cc_set_param().

831 {
832  /* 0 is an unreasonable value for any timer. Stick with the default */
833  if (value == 0) {
834  ast_log(LOG_WARNING, "0 is an invalid value for ccbs_available_timer. Retaining value as %u\n", config->ccbs_available_timer);
835  return;
836  }
837  config->ccbs_available_timer = value;
838 }
#define LOG_WARNING
Definition: logger.h:144
int value
Definition: syslog.c:39
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned int ccbs_available_timer
Definition: ccss.c:157
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 800 of file ccss.c.

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

Referenced by ast_cc_set_param().

801 {
802  /* 0 is an unreasonable value for any timer. Stick with the default */
803  if (value == 0) {
804  ast_log(LOG_WARNING, "0 is an invalid value for ccnr_available_timer. Retaining value as %u\n", config->ccnr_available_timer);
805  return;
806  }
807  config->ccnr_available_timer = value;
808 }
#define LOG_WARNING
Definition: logger.h:144
unsigned int ccnr_available_timer
Definition: ccss.c:156
int value
Definition: syslog.c:39
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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 3139 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, and cc_core_instance::monitors.

Referenced by generic_recall(), handle_request_invite(), and sig_pri_handle_subcmds().

3140 {
3141  struct ast_datastore *recall_datastore = ast_datastore_alloc(&recall_ds_info, NULL);
3142  struct cc_recall_ds_data *recall_data;
3143  struct cc_core_instance *core_instance;
3144 
3145  if (!recall_datastore) {
3146  return -1;
3147  }
3148 
3149  if (!(recall_data = ast_calloc(1, sizeof(*recall_data)))) {
3150  ast_datastore_free(recall_datastore);
3151  return -1;
3152  }
3153 
3154  if (!(core_instance = find_cc_core_instance(core_id))) {
3155  ast_free(recall_data);
3156  ast_datastore_free(recall_datastore);
3157  return -1;
3158  }
3159 
3160  recall_data->interface_tree = cc_ref(core_instance->monitors,
3161  "Bump refcount for monitor tree for recall datastore");
3162  recall_data->core_id = core_id;
3163  recall_datastore->data = recall_data;
3164  recall_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
3165  ast_channel_lock(chan);
3166  ast_channel_datastore_add(chan, recall_datastore);
3167  ast_channel_unlock(chan);
3168  cc_unref(core_instance, "Recall datastore set up. No need for core_instance ref");
3169  return 0;
3170 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
#define ast_channel_lock(chan)
Definition: channel.h:2466
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:421
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
Structure for a data store object.
Definition: datastore.h:54
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_free(a)
Definition: astmm.h:97
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:156
unsigned int inheritance
Definition: datastore.h:58
void * data
Definition: datastore.h:56
#define ast_calloc(a, b)
Definition: astmm.h:82
static struct ast_datastore_info recall_ds_info
Definition: ccss.c:3133
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3109
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
static void build_cc_interfaces_chanvar ( struct ast_cc_monitor starting_point,
struct ast_str **  str 
)
static

Definition at line 3322 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, 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().

3323 {
3324  struct extension_monitor_pvt *extension_pvt;
3325  struct extension_child_dialstring *child_dialstring;
3326  struct ast_cc_monitor *monitor_iter = starting_point;
3327  int top_level_id = starting_point->id;
3328  size_t length;
3329 
3330  /* Init to an empty string. */
3331  ast_str_truncate(*str, 0);
3332 
3333  /* First we need to take all of the is_valid child_dialstrings from
3334  * the extension monitor we found and add them to the CC_INTERFACES
3335  * chanvar
3336  */
3337  extension_pvt = starting_point->private_data;
3338  AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
3339  if (child_dialstring->is_valid) {
3340  cc_unique_append(str, child_dialstring->original_dialstring);
3341  }
3342  }
3343 
3344  /* And now we get the dialstrings from each of the device monitors */
3345  while ((monitor_iter = AST_LIST_NEXT(monitor_iter, next))) {
3346  if (monitor_iter->parent_id == top_level_id) {
3347  cc_unique_append(str, monitor_iter->dialstring);
3348  }
3349  }
3350 
3351  /* str will have an extra '&' tacked onto the end of it, so we need
3352  * to get rid of that.
3353  */
3354  length = ast_str_strlen(*str);
3355  if (length) {
3356  ast_str_truncate(*str, length - 1);
3357  }
3358  if (length <= 1) {
3359  /* Nothing to recall? This should not happen. */
3360  ast_log(LOG_ERROR, "CC_INTERFACES is empty. starting device_name:'%s'\n",
3361  starting_point->interface->device_name);
3362  }
3363 }
static void cc_unique_append(struct ast_str **str, const char *dialstring)
Definition: ccss.c:3292
struct ast_cc_monitor * next
Definition: ccss.h:545
unsigned int id
Definition: ccss.h:502
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition: ccss.c:1540
#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:507
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:521
#define LOG_ERROR
Definition: logger.h:155
struct extension_monitor_pvt::@235 child_dialstrings
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#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:526
struct ast_cc_interface * interface
Definition: ccss.h:497
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
char original_dialstring[AST_CHANNEL_NAME]
the original dialstring used to call a particular device
Definition: ccss.c:1506
Data regarding an extension monitor&#39;s child&#39;s dialstrings.
Definition: ccss.c:1490
Private data for an extension monitor.
Definition: ccss.c:1547
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:544
char device_name[1]
Definition: ccss.h:822
static void call_destructor_with_no_monitor ( const char *const  monitor_type,
void *  private_data 
)
static

Definition at line 1946 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().

1947 {
1948  const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type);
1949 
1950  if (!monitor_callbacks) {
1951  return;
1952  }
1953 
1954  monitor_callbacks->destructor(private_data);
1955 }
static struct ast_cc_monitor_callbacks * find_monitor_callbacks(const char *const type)
Definition: ccss.c:911
void(* destructor)(void *private_data)
Destroy private data on the monitor.
Definition: ccss.h:651
Callbacks defined by CC monitors.
Definition: ccss.h:559
static void cancel_available_timer ( struct cc_core_instance core_instance)
static

Definition at line 2955 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, and ast_cc_monitor::parent_id.

Referenced by cc_recalling().

2956 {
2957  struct ast_cc_monitor *monitor_iter;
2958  AST_LIST_LOCK(core_instance->monitors);
2959  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
2960  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
2961  if (monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id)) {
2963  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
2964  monitor_iter->interface->device_name, 1);
2965  cc_unref(monitor_iter, "cancel_available_timer failed. Unref list's reference to monitor");
2966  }
2967  }
2968  }
2970 
2971  if (!has_device_monitors(core_instance)) {
2972  ast_cc_failed(core_instance->core_id, "All device monitors failed to cancel their available timers");
2973  }
2974  AST_LIST_UNLOCK(core_instance->monitors);
2975 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
struct ast_cc_monitor * next
Definition: ccss.h:545
#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:3613
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void cc_extension_monitor_change_is_valid(struct cc_core_instance *core_instance, unsigned int parent_id, const char *const device_name, int is_valid)
Definition: ccss.c:1780
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
unsigned int parent_id
Definition: ccss.h:507
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
struct ast_cc_interface * interface
Definition: ccss.h:497
int(* cancel_available_timer)(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
Definition: ccss.h:640
int available_timer_id
Definition: ccss.h:530
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:2809
#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:822
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:534
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
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 2888 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_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, manager_event, ast_cc_agent_callbacks::respond, and unsuspend().

2889 {
2890  /* Either
2891  * 1. Callee accepted CC request, call agent's ack callback.
2892  * 2. Caller became available, call agent's stop_monitoring callback and
2893  * call monitor's unsuspend callback.
2894  */
2895  if (previous_state == CC_CALLER_REQUESTED) {
2896  core_instance->agent->callbacks->respond(core_instance->agent,
2898  manager_event(EVENT_FLAG_CC, "CCRequestAcknowledged",
2899  "CoreID: %d\r\n"
2900  "Caller: %s\r\n",
2901  core_instance->core_id, core_instance->agent->device_name);
2902  } else if (previous_state == CC_CALLER_BUSY) {
2903  manager_event(EVENT_FLAG_CC, "CCCallerStopMonitoring",
2904  "CoreID: %d\r\n"
2905  "Caller: %s\r\n",
2906  core_instance->core_id, core_instance->agent->device_name);
2907  unsuspend(core_instance);
2908  }
2909  /* Not possible for previous_state to be anything else due to the is_state_change_valid check at the beginning */
2910  return 0;
2911 }
static void unsuspend(struct cc_core_instance *core_instance)
Definition: ccss.c:2866
#define EVENT_FLAG_CC
Definition: manager.h:86
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
char device_name[1]
Definition: ccss.h:858
struct ast_cc_agent * agent
Definition: ccss.c:331
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition: ccss.h:948
static int cc_agent_callback_helper ( void *  obj,
void *  args,
int  flags 
)
static

Definition at line 434 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().

435 {
436  struct cc_core_instance *core_instance = obj;
437  struct cc_callback_helper *helper = args;
438 
439  if (strcmp(core_instance->agent->callbacks->type, helper->type)) {
440  return 0;
441  }
442 
443  return helper->function(core_instance->agent, helper->args, flags);
444 }
const char * type
Definition: ccss.c:431
ao2_callback_fn * function
Definition: ccss.c:429
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:877
static struct @350 args
struct ast_cc_agent * agent
Definition: ccss.c:331
void * args
Definition: ccss.c:430
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 2291 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, ast_cc_agent::cc_params, cc_unref(), check_callback_sanity(), ast_cc_agent::core_id, ast_cc_agent::device_name, find_agent_callbacks(), and ast_cc_agent_callbacks::init.

Referenced by cc_core_init_instance().

2294 {
2295  struct ast_cc_agent *agent;
2296  struct ast_cc_config_params *cc_params;
2297 
2298  if (!(agent = ao2_t_alloc(sizeof(*agent) + strlen(caller_name), agent_destroy,
2299  "Allocating new ast_cc_agent"))) {
2300  return NULL;
2301  }
2302 
2303  agent->core_id = core_id;
2304  strcpy(agent->device_name, caller_name);
2305 
2306  cc_params = ast_channel_get_cc_config_params(caller_chan);
2307  if (!cc_params) {
2308  cc_unref(agent, "Could not get channel config params.");
2309  return NULL;
2310  }
2311  if (!(agent->cc_params = ast_cc_config_params_init())) {
2312  cc_unref(agent, "Could not init agent config params.");
2313  return NULL;
2314  }
2315  ast_cc_copy_config_params(agent->cc_params, cc_params);
2316 
2317  if (!(agent->callbacks = find_agent_callbacks(caller_chan))) {
2318  cc_unref(agent, "Could not find agent callbacks.");
2319  return NULL;
2320  }
2322 
2323  if (agent->callbacks->init(agent, caller_chan)) {
2324  cc_unref(agent, "Agent init callback failed.");
2325  return NULL;
2326  }
2327  ast_log_dynamic_level(cc_logger_level, "Core %u: Created an agent for caller %s\n",
2328  agent->core_id, agent->device_name);
2329  return agent;
2330 }
int(* init)(struct ast_cc_agent *agent, struct ast_channel *chan)
CC agent initialization.
Definition: ccss.h:896
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:429
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
struct ast_cc_config_params * cc_params
Definition: ccss.h:842
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition: ccss.h:135
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
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:9754
static void check_callback_sanity(const struct ast_cc_agent_callbacks *callbacks)
Definition: ccss.c:2269
unsigned int core_id
Definition: ccss.h:832
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:741
char device_name[1]
Definition: ccss.h:858
static struct ast_cc_agent_callbacks * find_agent_callbacks(struct ast_channel *chan)
Definition: ccss.c:980
static int cc_logger_level
Definition: ccss.c:124
static void agent_destroy(void *data)
Definition: ccss.c:2281
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 2769 of file ccss.c.

References ast_log(), and LOG_WARNING.

2770 {
2771  /* This should never happen... */
2772  ast_log(LOG_WARNING, "Someone requested to change to CC_AVAILABLE? Ignoring.\n");
2773  return -1;
2774 }
#define LOG_WARNING
Definition: logger.h:144
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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 3858 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, 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().

3861 {
3862  struct ast_datastore *datastore;
3863  struct dialed_cc_interfaces *cc_interfaces;
3864  int dial_parent_id;
3865 
3866  ast_channel_lock(chan);
3867  datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL);
3868  if (!datastore) {
3869  ast_channel_unlock(chan);
3870  return -1;
3871  }
3872  cc_interfaces = datastore->data;
3873  dial_parent_id = cc_interfaces->dial_parent_id;
3874  ast_channel_unlock(chan);
3875 
3876  payload->monitor_type = monitor_type;
3877  payload->private_data = private_data;
3878  payload->service = service;
3879  ast_cc_copy_config_params(&payload->config_params, cc_params);
3881  ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
3882  ast_copy_string(payload->dialstring, dialstring, sizeof(payload->dialstring));
3883  return 0;
3884 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
void * private_data
Private data allocated by the callee.
Definition: ccss.c:247
int parent_interface_id
ID of parent extension.
Definition: ccss.c:274
enum ast_cc_service_type service
Definition: chan_sip.c:821
Structure for a data store object.
Definition: datastore.h:54
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:2604
char device_name[AST_CHANNEL_NAME]
Name of device to be monitored.
Definition: ccss.c:283
char dialstring[AST_CHANNEL_NAME]
Recall dialstring.
Definition: ccss.c:295
static struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1719
enum ast_cc_service_type service
Service offered by the endpoint.
Definition: ccss.c:256
#define ast_channel_unlock(chan)
Definition: channel.h:2467
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:741
void * data
Definition: datastore.h:56
struct ast_cc_config_params config_params
Configuration parameters used by this endpoint.
Definition: ccss.c:265
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:230
unsigned int dial_parent_id
Definition: ccss.c:1632
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 2913 of file ccss.c.

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

2914 {
2915  core_instance->agent->callbacks->callee_available(core_instance->agent);
2916  return 0;
2917 }
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
int(* callee_available)(struct ast_cc_agent *agent)
Alert the caller that it is time to try recalling.
Definition: ccss.h:1041
struct ast_cc_agent * agent
Definition: ccss.c:331
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 2941 of file ccss.c.

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

2942 {
2943  /* Callee was available, but caller was busy, call agent's begin_monitoring callback
2944  * and call monitor's suspend callback.
2945  */
2946  suspend(core_instance);
2947  core_instance->agent->callbacks->start_monitoring(core_instance->agent);
2948  manager_event(EVENT_FLAG_CC, "CCCallerStartMonitoring",
2949  "CoreID: %d\r\n"
2950  "Caller: %s\r\n",
2951  core_instance->core_id, core_instance->agent->device_name);
2952  return 0;
2953 }
#define EVENT_FLAG_CC
Definition: manager.h:86
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
static void suspend(struct cc_core_instance *core_instance)
Definition: ccss.c:2919
int(* start_monitoring)(struct ast_cc_agent *agent)
Begin monitoring a busy device.
Definition: ccss.h:1022
char device_name[1]
Definition: ccss.h:858
struct ast_cc_agent * agent
Definition: ccss.c:331
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
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 2776 of file ccss.c.

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

2777 {
2778  if (core_instance->agent->callbacks->start_offer_timer(core_instance->agent)) {
2779  ast_cc_failed(core_instance->core_id, "Failed to start the offer timer for %s\n",
2780  core_instance->agent->device_name);
2781  return -1;
2782  }
2783  manager_event(EVENT_FLAG_CC, "CCOfferTimerStart",
2784  "CoreID: %d\r\n"
2785  "Caller: %s\r\n"
2786  "Expires: %u\r\n",
2787  core_instance->core_id, core_instance->agent->device_name, core_instance->agent->cc_params->cc_offer_timer);
2788  ast_log_dynamic_level(cc_logger_level, "Core %d: Started the offer timer for the agent %s!\n",
2789  core_instance->core_id, core_instance->agent->device_name);
2790  return 0;
2791 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3613
struct ast_cc_config_params * cc_params
Definition: ccss.h:842
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define EVENT_FLAG_CC
Definition: manager.h:86
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
char device_name[1]
Definition: ccss.h:858
int(* start_offer_timer)(struct ast_cc_agent *agent)
Start the offer timer.
Definition: ccss.h:917
struct ast_cc_agent * agent
Definition: ccss.c:331
static int cc_logger_level
Definition: ccss.c:124
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
unsigned int cc_offer_timer
Definition: ccss.c:155
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 2852 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.

2853 {
2855  ast_log(LOG_WARNING, "Cannot request CC since there is no more room for requests\n");
2856  core_instance->agent->callbacks->respond(core_instance->agent,
2858  ast_cc_failed(core_instance->core_id, "Too many requests in the system");
2859  return -1;
2860  }
2861  core_instance->agent->callbacks->stop_offer_timer(core_instance->agent);
2862  request_cc(core_instance);
2863  return 0;
2864 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3613
#define LOG_WARNING
Definition: logger.h:144
int(* stop_offer_timer)(struct ast_cc_agent *agent)
Stop the offer timer.
Definition: ccss.h:930
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
static void request_cc(struct cc_core_instance *core_instance)
Definition: ccss.c:2824
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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:2219
struct ast_cc_agent * agent
Definition: ccss.c:331
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition: ccss.h:948
static int cc_cli_output_status ( void *  data)
static

Definition at line 4178 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().

4179 {
4180  int *cli_fd = data;
4182 
4183  if (!count) {
4184  ast_cli(*cli_fd, "There are currently no active call completion transactions\n");
4185  } else {
4186  ast_cli(*cli_fd, "%d Call completion transactions\n", count);
4187  ast_cli(*cli_fd, "Core ID\t\tCaller\t\t\t\tStatus\n");
4188  ast_cli(*cli_fd, "----------------------------------------------------------------------------\n");
4189  ao2_t_callback(cc_core_instances, OBJ_NODATA, print_stats_cb, cli_fd, "Printing stats to CLI");
4190  }
4191  ast_free(cli_fd);
4192  return 0;
4193 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#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:909
#define ast_free(a)
Definition: astmm.h:97
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
static int print_stats_cb(void *obj, void *arg, int flags)
Definition: ccss.c:4165
static void cc_cli_print_monitor_stats ( struct ast_cc_monitor monitor,
int  fd,
int  parent_id 
)
static

Definition at line 4145 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::parent_id, and ast_cc_monitor::service_offered.

Referenced by print_stats_cb().

4146 {
4147  struct ast_cc_monitor *child_monitor_iter = monitor;
4148  if (!monitor) {
4149  return;
4150  }
4151 
4152  ast_cli(fd, "\t\t|-->%s", monitor->interface->device_name);
4153  if (monitor->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
4154  ast_cli(fd, "(%s)", cc_service_to_string(monitor->service_offered));
4155  }
4156  ast_cli(fd, "\n");
4157 
4158  while ((child_monitor_iter = AST_LIST_NEXT(child_monitor_iter, next))) {
4159  if (child_monitor_iter->parent_id == monitor->id) {
4160  cc_cli_print_monitor_stats(child_monitor_iter, fd, child_monitor_iter->id);
4161  }
4162  }
4163 }
static const char * cc_service_to_string(enum ast_cc_service_type service)
Definition: ccss.c:402
struct ast_cc_monitor * next
Definition: ccss.h:545
unsigned int id
Definition: ccss.h:502
#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: cli.c:105
unsigned int parent_id
Definition: ccss.h:507
static unsigned int monitor
Definition: chan_phone.c:108
struct ast_cc_interface * interface
Definition: ccss.h:497
static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
Definition: ccss.c:4145
char device_name[1]
Definition: ccss.h:822
enum ast_cc_service_type service_offered
Definition: ccss.h:515
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
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 2989 of file ccss.c.

References cc_core_instance::agent, ao2_t_unlink, cc_core_instance::core_id, ast_cc_agent::device_name, EVENT_FLAG_CC, and manager_event.

2990 {
2991  /* Recall has made progress, call agent and monitor destructor functions
2992  */
2993  manager_event(EVENT_FLAG_CC, "CCRecallComplete",
2994  "CoreID: %d\r\n"
2995  "Caller: %s\r\n",
2996  core_instance->core_id, core_instance->agent->device_name);
2997  ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC recall has completed");
2998  return 0;
2999 }
#define EVENT_FLAG_CC
Definition: manager.h:86
#define ao2_t_unlink(arg1, arg2, arg3)
Remove an object from a container.
Definition: astobj2.h:816
char device_name[1]
Definition: ccss.h:858
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
struct ast_cc_agent * agent
Definition: ccss.c:331
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
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 2652 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_ref(), cc_unref(), cc_core_instance::core_id, count_agents(), kill_duplicate_offers(), and cc_core_instance::monitors.

Referenced by ast_handle_cc_control_frame().

2654 {
2655  char caller[AST_CHANNEL_NAME];
2656  struct cc_core_instance *core_instance;
2657  struct ast_cc_config_params *cc_params;
2658  long agent_count;
2659  int recall_core_id;
2660 
2661  ast_channel_get_device_name(caller_chan, caller, sizeof(caller));
2662  cc_params = ast_channel_get_cc_config_params(caller_chan);
2663  if (!cc_params) {
2664  ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n",
2665  caller);
2666  return NULL;
2667  }
2668  /* First, we need to kill off other pending CC offers from caller. If the caller is going
2669  * to request a CC service, it may only be for the latest call he made.
2670  */
2671  if (ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
2672  kill_duplicate_offers(caller);
2673  }
2674 
2675  ast_cc_is_recall(caller_chan, &recall_core_id, NULL);
2676  agent_count = count_agents(caller, recall_core_id);
2677  if (agent_count >= ast_get_cc_max_agents(cc_params)) {
2678  ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller);
2679  return NULL;
2680  }
2681 
2682  /* Generic agents can only have a single outstanding CC request per caller. */
2683  if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
2684  ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n");
2685  return NULL;
2686  }
2687 
2688  /* Next, we need to create the core instance for this call */
2689  if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) {
2690  return NULL;
2691  }
2692 
2693  core_instance->core_id = core_id;
2694  if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) {
2695  cc_unref(core_instance, "Couldn't allocate agent, unref core_instance");
2696  return NULL;
2697  }
2698 
2699  core_instance->monitors = cc_ref(called_tree, "Core instance getting ref to monitor tree");
2700 
2701  ao2_t_link(cc_core_instances, core_instance, "Link core instance into container");
2702 
2703  return core_instance;
2704 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:429
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
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:3172
unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config)
Get the cc_max_agents.
Definition: ccss.c:854
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:9754
#define ao2_t_link(arg1, arg2, arg3)
Add an object to a container.
Definition: astobj2.h:784
#define AST_CHANNEL_NAME
Definition: channel.h:137
static void kill_duplicate_offers(char *caller)
Definition: ccss.c:2252
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:2291
static void cc_core_instance_destructor(void *data)
Definition: ccss.c:2640
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
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:9776
static long count_agents(const char *const caller, const int core_id_exception)
Definition: ccss.c:2243
struct ast_cc_agent * agent
Definition: ccss.c:331
static int cc_logger_level
Definition: ccss.c:124
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:746
static int cc_core_instance_cmp_fn ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 413 of file ccss.c.

References CMP_MATCH, CMP_STOP, and cc_core_instance::core_id.

Referenced by ast_cc_init().

414 {
415  struct cc_core_instance *core_instance1 = obj;
416  struct cc_core_instance *core_instance2 = arg;
417 
418  return core_instance1->core_id == core_instance2->core_id ? CMP_MATCH | CMP_STOP : 0;
419 }
static void cc_core_instance_destructor ( void *  data)
static

Definition at line 2640 of file ccss.c.

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

Referenced by cc_core_init_instance().

2641 {
2642  struct cc_core_instance *core_instance = data;
2643  ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying core instance\n", core_instance->core_id);
2644  if (core_instance->agent) {
2645  cc_unref(core_instance->agent, "Core instance is done with the agent now");
2646  }
2647  if (core_instance->monitors) {
2648  core_instance->monitors = cc_unref(core_instance->monitors, "Core instance is done with interface list");
2649  }
2650 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
struct ast_cc_agent * agent
Definition: ccss.c:331
static int cc_logger_level
Definition: ccss.c:124
static int cc_core_instance_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 407 of file ccss.c.

References cc_core_instance::core_id.

Referenced by ast_cc_init().

408 {
409  const struct cc_core_instance *core_instance = obj;
410  return core_instance->core_id;
411 }
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 1982 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_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, 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().

1983 {
1984  struct ast_cc_interface *cc_interface;
1985  struct ast_cc_monitor *monitor;
1986  size_t device_name_len = strlen(device_name);
1987  int parent_id = cc_data->parent_interface_id;
1988 
1989  if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + device_name_len, cc_interface_destroy,
1990  "Allocating new ast_cc_interface"))) {
1991  return NULL;
1992  }
1993 
1994  if (!(cc_interface->config_params = ast_cc_config_params_init())) {
1995  cc_unref(cc_interface, "Failed to allocate config params, unref interface");
1996  return NULL;
1997  }
1998 
1999  if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
2000  cc_unref(cc_interface, "Failed to allocate monitor, unref interface");
2001  return NULL;
2002  }
2003 
2004  if (!(monitor->dialstring = ast_strdup(dialstring))) {
2005  cc_unref(monitor, "Failed to copy dialable name. Unref monitor");
2006  cc_unref(cc_interface, "Failed to copy dialable name");
2007  return NULL;
2008  }
2009 
2010  if (!(monitor->callbacks = find_monitor_callbacks(cc_data->monitor_type))) {
2011  cc_unref(monitor, "Failed to find monitor callbacks. Unref monitor");
2012  cc_unref(cc_interface, "Failed to find monitor callbacks");
2013  return NULL;
2014  }
2015 
2016  strcpy(cc_interface->device_name, device_name);
2018  monitor->parent_id = parent_id;
2019  monitor->core_id = core_id;
2020  monitor->service_offered = cc_data->service;
2021  monitor->private_data = cc_data->private_data;
2022  cc_interface->monitor_type = cc_data->monitor_type;
2023  cc_interface->monitor_class = AST_CC_DEVICE_MONITOR;
2024  monitor->interface = cc_interface;
2025  monitor->available_timer_id = -1;
2026  ast_cc_copy_config_params(cc_interface->config_params, &cc_data->config_params);
2027  ast_log_dynamic_level(cc_logger_level, "Core %d: Created a device cc interface for '%s' with id %u and parent %u\n",
2028  monitor->core_id, cc_interface->device_name, monitor->id, monitor->parent_id);
2029  return monitor;
2030 }
void * private_data
Private data allocated by the callee.
Definition: ccss.c:247
#define ast_strdup(a)
Definition: astmm.h:109
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:429
unsigned int id
Definition: ccss.h:502
static int dialed_cc_interface_counter
Definition: ccss.c:1605
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static void cc_interface_destroy(void *data)
Definition: ccss.c:1467
int parent_interface_id
ID of parent extension.
Definition: ccss.c:274
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
static struct ast_cc_monitor_callbacks * find_monitor_callbacks(const char *const type)
Definition: ccss.c:911
#define ast_cc_config_params_init()
Allocate and initialize an ast_cc_config_params structure.
Definition: ccss.h:135
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
unsigned int parent_id
Definition: ccss.h:507
int core_id
Definition: ccss.h:511
Structure with information about an outbound interface.
Definition: ccss.h:801
struct ast_cc_config_params * config_params
Definition: ccss.h:817
static void cc_monitor_destroy(void *data)
Definition: ccss.c:1567
static unsigned int monitor
Definition: chan_phone.c:108
enum ast_cc_service_type service
Service offered by the endpoint.
Definition: ccss.c:256
char * dialstring
Name that should be used to recall specified interface.
Definition: ccss.h:526
const char * monitor_type
The type of monitor that should be used for this interface.
Definition: ccss.h:813
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:741
struct ast_cc_interface * interface
Definition: ccss.h:497
struct ast_cc_config_params config_params
Configuration parameters used by this endpoint.
Definition: ccss.c:265
int available_timer_id
Definition: ccss.h:530
const char * monitor_type
The type of monitor to allocate.
Definition: ccss.c:230
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:544
char device_name[1]
Definition: ccss.h:822
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:534
static int cc_logger_level
Definition: ccss.c:124
enum ast_cc_service_type service_offered
Definition: ccss.h:515
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
static int cc_do_state_change ( void *  datap)
static

Definition at line 3024 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_state_to_string(), cc_unref(), 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().

3025 {
3026  struct cc_state_change_args *args = datap;
3027  struct cc_core_instance *core_instance;
3028  enum cc_state previous_state;
3029  int res;
3030 
3031  ast_log_dynamic_level(cc_logger_level, "Core %d: State change to %u requested. Reason: %s\n",
3032  args->core_id, args->state, args->debug);
3033 
3034  core_instance = args->core_instance;
3035 
3036  if (!is_state_change_valid(core_instance->current_state, args->state, core_instance->agent)) {
3037  ast_log_dynamic_level(cc_logger_level, "Core %d: Invalid state change requested. Cannot go from %s to %s\n",
3038  args->core_id, cc_state_to_string(core_instance->current_state), cc_state_to_string(args->state));
3039  if (args->state == CC_CALLER_REQUESTED) {
3040  /*
3041  * For out-of-order requests, we need to let the requester know that
3042  * we can't handle the request now.
3043  */
3044  core_instance->agent->callbacks->respond(core_instance->agent,
3046  }
3047  ast_free(args);
3048  cc_unref(core_instance, "Unref core instance from when it was found earlier");
3049  return -1;
3050  }
3051 
3052  /* We can change to the new state now. */
3053  previous_state = core_instance->current_state;
3054  core_instance->current_state = args->state;
3055  res = state_change_funcs[core_instance->current_state](core_instance, args, previous_state);
3056 
3057  ast_free(args);
3058  cc_unref(core_instance, "Unref since state change has completed"); /* From ao2_find */
3059  return res;
3060 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
enum cc_state state
Definition: ccss.c:2708
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
struct cc_core_instance * core_instance
Definition: ccss.c:2707
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
static const char * cc_state_to_string(enum cc_state state)
Definition: ccss.c:397
cc_state
The states used in the CCSS core state machine.
Definition: ccss.c:171
static int(*const state_change_funcs[])(struct cc_core_instance *, struct cc_state_change_args *, enum cc_state previous_state)
Definition: ccss.c:3012
static struct @350 args
enum cc_state current_state
Definition: ccss.c:327
#define ast_free(a)
Definition: astmm.h:97
static int is_state_change_valid(enum cc_state current_state, const enum cc_state new_state, struct ast_cc_agent *agent)
Definition: ccss.c:2713
struct ast_cc_agent * agent
Definition: ccss.c:331
static int cc_logger_level
Definition: ccss.c:124
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition: ccss.h:948
static void cc_extension_monitor_change_is_valid ( struct cc_core_instance core_instance,
unsigned int  parent_id,
const char *const  device_name,
int  is_valid 
)
static

Definition at line 1780 of file ccss.c.

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

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

1781 {
1782  struct ast_cc_monitor *monitor_iter;
1783  struct extension_monitor_pvt *extension_pvt;
1784  struct extension_child_dialstring *child_dialstring;
1785 
1786  AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
1787  if (monitor_iter->id == parent_id) {
1788  break;
1789  }
1790  }
1791 
1792  if (!monitor_iter) {
1793  return;
1794  }
1795  extension_pvt = monitor_iter->private_data;
1796 
1797  AST_LIST_TRAVERSE(&extension_pvt->child_dialstrings, child_dialstring, next) {
1798  if (!strcmp(child_dialstring->device_name, device_name)) {
1799  child_dialstring->is_valid = is_valid;
1800  break;
1801  }
1802  }
1803 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
unsigned int id
Definition: ccss.h:502
int is_valid
Is this structure valid for use in CC_INTERFACES?
Definition: ccss.c:1540
struct extension_child_dialstring * next
Definition: ccss.c:1541
char device_name[AST_CHANNEL_NAME]
The name of the device being dialed.
Definition: ccss.c:1525
struct extension_monitor_pvt::@235 child_dialstrings
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
Data regarding an extension monitor&#39;s child&#39;s dialstrings.
Definition: ccss.c:1490
Private data for an extension monitor.
Definition: ccss.c:1547
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:544
static void cc_extension_monitor_destructor ( void *  private_data)
static

Definition at line 1551 of file ccss.c.

References ast_free, AST_LIST_REMOVE_HEAD, and extension_monitor_pvt::child_dialstrings.

Referenced by cc_monitor_destroy().

1552 {
1553  struct extension_monitor_pvt *extension_pvt = private_data;
1554  struct extension_child_dialstring *child_dialstring;
1555 
1556  /* This shouldn't be possible, but I'm paranoid */
1557  if (!extension_pvt) {
1558  return;
1559  }
1560 
1561  while ((child_dialstring = AST_LIST_REMOVE_HEAD(&extension_pvt->child_dialstrings, next))) {
1562  ast_free(child_dialstring);
1563  }
1564  ast_free(extension_pvt);
1565 }
struct extension_child_dialstring * next
Definition: ccss.c:1541
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct extension_monitor_pvt::@235 child_dialstrings
#define ast_free(a)
Definition: astmm.h:97
Data regarding an extension monitor&#39;s child&#39;s dialstrings.
Definition: ccss.c:1490
Private data for an extension monitor.
Definition: ccss.c:1547
static struct ast_cc_monitor* cc_extension_monitor_init ( const char *const  exten,
const char *const  context,
const unsigned int  parent_id 
)
static

Definition at line 1819 of file ccss.c.

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

Referenced by ast_cc_call_init(), and cc_interfaces_datastore_init().

1820 {
1822  struct ast_cc_interface *cc_interface;
1823  struct ast_cc_monitor *monitor;
1824 
1825  ast_str_set(&str, 0, "%s@%s", exten, context);
1826 
1827  if (!(cc_interface = ao2_t_alloc(sizeof(*cc_interface) + ast_str_strlen(str), cc_interface_destroy,
1828  "Allocating new ast_cc_interface"))) {
1829  return NULL;
1830  }
1831 
1832  if (!(monitor = ao2_t_alloc(sizeof(*monitor), cc_monitor_destroy, "Allocating new ast_cc_monitor"))) {
1833  cc_unref(cc_interface, "failed to allocate the monitor, so unref the interface");
1834  return NULL;
1835  }
1836 
1837  if (!(monitor->private_data = extension_monitor_pvt_init())) {
1838  cc_unref(monitor, "Failed to initialize extension monitor private data. uref monitor");
1839  cc_unref(cc_interface, "Failed to initialize extension monitor private data. unref cc_interface");
1840  }
1841 
1843  monitor->parent_id = parent_id;
1844  cc_interface->monitor_type = "extension";
1845  cc_interface->monitor_class = AST_CC_EXTENSION_MONITOR;
1846  strcpy(cc_interface->device_name, ast_str_buffer(str));
1847  monitor->interface = cc_interface;
1848  ast_log_dynamic_level(cc_logger_level, "Created an extension cc interface for '%s' with id %u and parent %u\n", cc_interface->device_name, monitor->id, monitor->parent_id);
1849  return monitor;
1850 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
static struct extension_monitor_pvt * extension_monitor_pvt_init(void)
Definition: ccss.c:1725
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:429
unsigned int id
Definition: ccss.h:502
static int dialed_cc_interface_counter
Definition: ccss.c:1605
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static void cc_interface_destroy(void *data)
Definition: ccss.c:1467
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define ast_str_alloca(init_len)
Definition: strings.h:608
const char * str
Definition: app_jack.c:144
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
unsigned int parent_id
Definition: ccss.h:507
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
Structure with information about an outbound interface.
Definition: ccss.h:801
#define AST_MAX_EXTENSION
Definition: channel.h:135
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
static void cc_monitor_destroy(void *data)
Definition: ccss.c:1567
static unsigned int monitor
Definition: chan_phone.c:108
const char * monitor_type
The type of monitor that should be used for this interface.
Definition: ccss.h:813
struct ast_cc_interface * interface
Definition: ccss.h:497
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:544
char device_name[1]
Definition: ccss.h:822
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int cc_logger_level
Definition: ccss.c:124
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
static int cc_failed ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 3001 of file ccss.c.

References cc_core_instance::agent, ao2_t_unlink, cc_core_instance::core_id, cc_state_change_args::debug, ast_cc_agent::device_name, EVENT_FLAG_CC, and manager_event.

3002 {
3003  manager_event(EVENT_FLAG_CC, "CCFailure",
3004  "CoreID: %d\r\n"
3005  "Caller: %s\r\n"
3006  "Reason: %s\r\n",
3007  core_instance->core_id, core_instance->agent->device_name, args->debug);
3008  ao2_t_unlink(cc_core_instances, core_instance, "Unlink core instance since CC failed");
3009  return 0;
3010 }
#define EVENT_FLAG_CC
Definition: manager.h:86
#define ao2_t_unlink(arg1, arg2, arg3)
Remove an object from a container.
Definition: astobj2.h:816
char device_name[1]
Definition: ccss.h:858
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
struct ast_cc_agent * agent
Definition: ccss.c:331
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
static void cc_generic_agent_destructor ( struct ast_cc_agent agent)
static

Definition at line 2623 of file ccss.c.

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

2624 {
2625  struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
2626 
2627  if (!agent_pvt) {
2628  /* The agent constructor probably failed. */
2629  return;
2630  }
2631 
2633  if (agent_pvt->sub) {
2634  agent_pvt->sub = ast_event_unsubscribe(agent_pvt->sub);
2635  }
2636 
2637  ast_free(agent_pvt);
2638 }
void * private_data
Definition: ccss.h:854
static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
Definition: ccss.c:2459
Structure representing an agent.
Definition: chan_agent.c:252
#define ast_free(a)
Definition: astmm.h:97
struct ast_event_sub * sub
Definition: ccss.c:2365
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
Definition: event.c:987
static int cc_generic_agent_init ( struct ast_cc_agent agent,
struct ast_channel chan 
)
static

Definition at line 2406 of file ccss.c.

References ast_calloc, AST_CC_AGENT_SKIP_OFFER, ast_copy_string(), ast_set_flag, ast_channel::caller, cc_generic_agent_pvt::cid_name, cc_generic_agent_pvt::cid_num, ast_channel::context, cc_generic_agent_pvt::context, ast_channel::exten, cc_generic_agent_pvt::exten, ast_party_caller::id, ast_channel::macrocontext, ast_channel::macroexten, ast_party_id::name, ast_party_id::number, cc_generic_agent_pvt::offer_timer_id, ast_cc_agent::private_data, S_OR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.

2407 {
2408  struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
2409 
2410  if (!generic_pvt) {
2411  return -1;
2412  }
2413 
2414  generic_pvt->offer_timer_id = -1;
2415  if (chan->caller.id.number.valid && chan->caller.id.number.str) {
2416  ast_copy_string(generic_pvt->cid_num, chan->caller.id.number.str, sizeof(generic_pvt->cid_num));
2417  }
2418  if (chan->caller.id.name.valid && chan->caller.id.name.str) {
2419  ast_copy_string(generic_pvt->cid_name, chan->caller.id.name.str, sizeof(generic_pvt->cid_name));
2420  }
2421  ast_copy_string(generic_pvt->exten, S_OR(chan->macroexten, chan->exten), sizeof(generic_pvt->exten));
2422  ast_copy_string(generic_pvt->context, S_OR(chan->macrocontext, chan->context), sizeof(generic_pvt->context));
2423  agent->private_data = generic_pvt;
2425  return 0;
2426 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
void * private_data
Definition: ccss.h:854
char cid_num[AST_CHANNEL_NAME]
Definition: ccss.c:2379
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define ast_set_flag(p, flag)
Definition: utils.h:70
char context[AST_CHANNEL_NAME]
Definition: ccss.c:2403
char * str
Subscriber name (Malloced)
Definition: channel.h:214
char exten[AST_CHANNEL_NAME]
Definition: ccss.c:2395
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
char cid_name[AST_CHANNEL_NAME]
Definition: ccss.c:2387
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int cc_generic_agent_recall ( struct ast_cc_agent agent)
static

Definition at line 2607 of file ccss.c.

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

2608 {
2609  pthread_t clotho;
2610  enum ast_device_state current_state = ast_device_state(agent->device_name);
2611 
2612  if (!cc_generic_is_device_available(current_state)) {
2613  /* We can't try to contact the device right now because he's not available
2614  * Let the core know he's busy.
2615  */
2616  ast_cc_agent_caller_busy(agent->core_id, "Generic agent caller %s is busy", agent->device_name);
2617  return 0;
2618  }
2620  return 0;
2621 }
ast_device_state
Device States.
Definition: devicestate.h:51
static void * generic_recall(void *data)
Definition: ccss.c:2548
int ast_cc_agent_caller_busy(int core_id, const char *const debug,...)
Indicate that the caller is busy.
Definition: ccss.c:3543
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:431
unsigned int core_id
Definition: ccss.h:832
char device_name[1]
Definition: ccss.h:858
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1024
static void cc_generic_agent_respond ( struct ast_cc_agent agent,
enum ast_cc_agent_response_reason  reason 
)
static

Definition at line 2472 of file ccss.c.

2473 {
2474  /* The generic agent doesn't have to do anything special to
2475  * acknowledge a CC request. Just return.
2476  */
2477  return;
2478 }
static int cc_generic_agent_start_monitoring ( struct ast_cc_agent agent)
static

Definition at line 2529 of file ccss.c.

References ast_assert, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_STATE, ast_event_subscribe(), ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_cc_agent::device_name, generic_agent_devstate_cb(), ast_cc_agent::private_data, str, and cc_generic_agent_pvt::sub.

2530 {
2531  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2532  struct ast_str *str = ast_str_alloca(128);
2533 
2534  ast_assert(generic_pvt->sub == NULL);
2535  ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n",
2536  agent->device_name);
2537 
2538  if (!(generic_pvt->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE,
2542  AST_EVENT_IE_END))) {
2543  return -1;
2544  }
2545  return 0;
2546 }
void * private_data
Definition: ccss.h:854
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
#define ast_assert(a)
Definition: utils.h:738
#define ast_str_alloca(init_len)
Definition: strings.h:608
const char * str
Definition: app_jack.c:144
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
char device_name[1]
Definition: ccss.h:858
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
Definition: event.c:909
struct ast_event_sub * sub
Definition: ccss.c:2365
static void generic_agent_devstate_cb(const struct ast_event *event, void *userdata)
Definition: ccss.c:2510
Generic State IE Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: UINT The actual state values dep...
Definition: event_defs.h:115
Device Name Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: STR.
Definition: event_defs.h:107
static int cc_generic_agent_start_offer_timer ( struct ast_cc_agent agent)
static

Definition at line 2440 of file ccss.c.

References ast_assert, ast_get_cc_offer_timer(), ast_log_dynamic_level, ast_sched_thread_add(), ast_cc_agent::cc_params, cc_ref(), ast_cc_agent::core_id, offer_timer_expire(), cc_generic_agent_pvt::offer_timer_id, and ast_cc_agent::private_data.

2441 {
2442  int when;
2443  int sched_id;
2444  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2445 
2446  ast_assert(cc_sched_thread != NULL);
2447  ast_assert(agent->cc_params != NULL);
2448 
2449  when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
2450  ast_log_dynamic_level(cc_logger_level, "Core %u: About to schedule offer timer expiration for %d ms\n",
2451  agent->core_id, when);
2452  if ((sched_id = ast_sched_thread_add(cc_sched_thread, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) {
2453  return -1;
2454  }
2455  generic_pvt->offer_timer_id = sched_id;
2456  return 0;
2457 }
void * private_data
Definition: ccss.h:854
struct ast_cc_config_params * cc_params
Definition: ccss.h:842
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
static struct ast_sched_thread * cc_sched_thread
Definition: ccss.c:106
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define ast_assert(a)
Definition: utils.h:738
static int offer_timer_expire(const void *data)
Definition: ccss.c:2428
unsigned int core_id
Definition: ccss.h:832
unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config)
Get the cc_offer_timer.
Definition: ccss.c:780
int ast_sched_thread_add(struct ast_sched_thread *st, int when, ast_sched_cb cb, const void *data)
Add a scheduler entry.
Definition: sched.c:210
static int cc_logger_level
Definition: ccss.c:124
static int cc_generic_agent_status_request ( struct ast_cc_agent agent)
static

Definition at line 2480 of file ccss.c.

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

2481 {
2483  return 0;
2484 }
ast_device_state
Device States.
Definition: devicestate.h:51
int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate)
Response with a caller&#39;s current status.
Definition: ccss.c:3830
unsigned int core_id
Definition: ccss.h:832
char device_name[1]
Definition: ccss.h:858
static int cc_generic_agent_stop_offer_timer ( struct ast_cc_agent agent)
static

Definition at line 2459 of file ccss.c.

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

Referenced by cc_generic_agent_destructor().

2460 {
2461  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2462 
2463  if (generic_pvt->offer_timer_id != -1) {
2464  if (!ast_sched_thread_del(cc_sched_thread, generic_pvt->offer_timer_id)) {
2465  cc_unref(agent, "Remove scheduler's reference to the agent");
2466  }
2467  generic_pvt->offer_timer_id = -1;
2468  }
2469  return 0;
2470 }
void * private_data
Definition: ccss.h:854
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static struct ast_sched_thread * cc_sched_thread
Definition: ccss.c:106
#define ast_sched_thread_del(st, id)
Delete a scheduler entry.
Definition: sched.h:403
static int cc_generic_agent_stop_ringing ( struct ast_cc_agent agent)
static

Definition at line 2486 of file ccss.c.

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

2487 {
2488  struct ast_channel *recall_chan = ast_channel_get_by_name_prefix(agent->device_name, strlen(agent->device_name));
2489 
2490  if (!recall_chan) {
2491  return 0;
2492  }
2493 
2495  return 0;
2496 }
Main Channel structure associated with a channel.
Definition: channel.h:742
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1808
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
char device_name[1]
Definition: ccss.h:858
static int cc_generic_monitor_cancel_available_timer ( struct ast_cc_monitor monitor,
int *  sched_id 
)
static

Definition at line 1381 of file ccss.c.

References ast_assert, ast_log_dynamic_level, ast_sched_thread_del, cc_unref(), ast_cc_monitor::core_id, ast_cc_interface::device_name, and ast_cc_monitor::interface.

1382 {
1383  ast_assert(sched_id != NULL);
1384 
1385  if (*sched_id == -1) {
1386  return 0;
1387  }
1388 
1389  ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n",
1390  monitor->core_id, monitor->interface->device_name);
1391  if (!ast_sched_thread_del(cc_sched_thread, *sched_id)) {
1392  cc_unref(monitor, "Remove scheduler's reference to the monitor");
1393  }
1394  *sched_id = -1;
1395  return 0;
1396 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static struct ast_sched_thread * cc_sched_thread
Definition: ccss.c:106
#define ast_sched_thread_del(st, id)
Delete a scheduler entry.
Definition: sched.h:403
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define ast_assert(a)
Definition: utils.h:738
int core_id
Definition: ccss.h:511
struct ast_cc_interface * interface
Definition: ccss.h:497
char device_name[1]
Definition: ccss.h:822
static int cc_logger_level
Definition: ccss.c:124
static void cc_generic_monitor_destructor ( void *  private_data)
static

Definition at line 1398 of file ccss.c.

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

1399 {
1400  struct generic_monitor_pvt *gen_mon_pvt = private_data;
1401  struct generic_monitor_instance_list *generic_list;
1402  struct generic_monitor_instance *generic_instance;
1403 
1404  if (!private_data) {
1405  /* If the private data is NULL, that means that the monitor hasn't even
1406  * been created yet, but that the destructor was called. While this sort
1407  * of behavior is useful for native monitors, with a generic one, there is
1408  * nothing in particular to do.
1409  */
1410  return;
1411  }
1412 
1413  ast_log_dynamic_level(cc_logger_level, "Core %d: Destroying generic monitor %s\n",
1414  gen_mon_pvt->core_id, gen_mon_pvt->device_name);
1415 
1416  if (!(generic_list = find_generic_monitor_instance_list(gen_mon_pvt->device_name))) {
1417  /* If there's no generic list, that means that the monitor is being destroyed
1418  * before we actually got to request CC. Not a biggie. Same in the situation
1419  * below if the list traversal should complete without finding an entry.
1420  */
1421  ast_free((char *)gen_mon_pvt->device_name);
1422  ast_free(gen_mon_pvt);
1423  return;
1424  }
1425 
1426  AST_LIST_TRAVERSE_SAFE_BEGIN(&generic_list->list, generic_instance, next) {
1427  if (generic_instance->core_id == gen_mon_pvt->core_id) {
1429  ast_free(generic_instance);
1430  break;
1431  }
1432  }
1434 
1435  if (AST_LIST_EMPTY(&generic_list->list)) {
1436  /* No more monitors with this device name exist. Time to unlink this
1437  * list from the container
1438  */
1439  ao2_t_unlink(generic_monitors, generic_list, "Generic list is empty. Unlink it from the container");
1440  } else {
1441  /* There are still instances for this particular device. The situation
1442  * may be that we were attempting a CC recall and a failure occurred, perhaps
1443  * on the agent side. If a failure happens here and the device being monitored
1444  * is available, then we need to signal on the first unsuspended instance that
1445  * the device is available for recall.
1446  */
1447 
1448  /* First things first. We don't even want to consider this action if
1449  * the device in question isn't available right now.
1450  */
1451  if (generic_list->fit_for_recall
1452  && cc_generic_is_device_available(generic_list->current_state)) {
1453  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1454  if (!generic_instance->is_suspended && generic_instance->monitoring) {
1455  ast_cc_monitor_callee_available(generic_instance->core_id, "Signaling generic monitor "
1456  "availability due to other instance's failure.");
1457  break;
1458  }
1459  }
1460  }
1461  }
1462  cc_unref(generic_list, "Done with generic list in generic monitor destructor");
1463  ast_free((char *)gen_mon_pvt->device_name);
1464  ast_free(gen_mon_pvt);
1465 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
struct generic_monitor_instance_list::@233 list
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
struct ao2_container * generic_monitors
Definition: ccss.c:1044
#define ao2_t_unlink(arg1, arg2, arg3)
Remove an object from a container.
Definition: astobj2.h:816
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1108
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:97
private data for generic device monitor
Definition: ccss.c:1079
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1024
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
const char * device_name
Definition: ccss.c:1084
static int cc_logger_level
Definition: ccss.c:124
enum ast_device_state current_state
Definition: ccss.c:1055
struct generic_monitor_instance * next
Definition: ccss.c:1050
int ast_cc_monitor_callee_available(const int core_id, const char *const debug,...)
Alert the core that a device being monitored has become available.
Definition: ccss.c:3532
static int cc_generic_monitor_request_cc ( struct ast_cc_monitor monitor,
int *  available_timer_id 
)
static

Definition at line 1249 of file ccss.c.

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

1250 {
1251  struct generic_monitor_instance_list *generic_list;
1252  struct generic_monitor_instance *generic_instance;
1253  struct generic_monitor_pvt *gen_mon_pvt;
1255  int when;
1256 
1257  /* First things first. Native channel drivers will have their private data allocated
1258  * at the time that they tell the core that they can offer CC. Generic is quite a bit
1259  * different, and we wait until this point to allocate our private data.
1260  */
1261  if (!(gen_mon_pvt = ast_calloc(1, sizeof(*gen_mon_pvt)))) {
1262  return -1;
1263  }
1264 
1265  if (!(gen_mon_pvt->device_name = ast_strdup(monitor->interface->device_name))) {
1266  ast_free(gen_mon_pvt);
1267  return -1;
1268  }
1269 
1270  gen_mon_pvt->core_id = monitor->core_id;
1271 
1272  monitor->private_data = gen_mon_pvt;
1273 
1274  if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1275  if (!(generic_list = create_new_generic_list(monitor))) {
1276  return -1;
1277  }
1278  }
1279 
1280  if (!(generic_instance = ast_calloc(1, sizeof(*generic_instance)))) {
1281  /* The generic monitor destructor will take care of the appropriate
1282  * deallocations
1283  */
1284  cc_unref(generic_list, "Generic monitor instance failed to allocate");
1285  return -1;
1286  }
1287  generic_instance->core_id = monitor->core_id;
1288  generic_instance->monitoring = 1;
1289  AST_LIST_INSERT_TAIL(&generic_list->list, generic_instance, next);
1290  when = service == AST_CC_CCBS ? ast_get_ccbs_available_timer(monitor->interface->config_params) :
1291  ast_get_ccnr_available_timer(monitor->interface->config_params);
1292 
1293  *available_timer_id = ast_sched_thread_add(cc_sched_thread, when * 1000,
1294  ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference"));
1295  if (*available_timer_id == -1) {
1296  cc_unref(monitor, "Failed to schedule available timer. (monitor)");
1297  cc_unref(generic_list, "Failed to schedule available timer. (generic_list)");
1298  return -1;
1299  }
1300  /* If the new instance was created as CCNR, then that means this device is not currently
1301  * fit for recall even if it previously was.
1302  */
1303  if (service == AST_CC_CCNR || service == AST_CC_CCNL) {
1304  generic_list->fit_for_recall = 0;
1305  }
1306  ast_cc_monitor_request_acked(monitor->core_id, "Generic monitor for %s subscribed to device state.",
1307  monitor->interface->device_name);
1308  cc_unref(generic_list, "Finished with monitor instance reference in request cc callback");
1309  return 0;
1310 }
#define ast_strdup(a)
Definition: astmm.h:109
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
struct generic_monitor_instance_list::@233 list
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
static struct ast_sched_thread * cc_sched_thread
Definition: ccss.c:106
int ast_cc_monitor_request_acked(int core_id, const char *const debug,...)
Indicate that an outbound entity has accepted our CC request.
Definition: ccss.c:3521
enum ast_cc_service_type service
Definition: chan_sip.c:821
int ast_cc_available_timer_expire(const void *data)
Scheduler callback for available timer expiration.
Definition: ccss.c:1239
ast_cc_service_type
Definition: ccss.h:32
unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config)
Get the ccbs_available_timer.
Definition: ccss.c:825
unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config)
Get the ccnr_available_timer.
Definition: ccss.c:795
int core_id
Definition: ccss.h:511
static struct generic_monitor_instance_list * create_new_generic_list(struct ast_cc_monitor *monitor)
Definition: ccss.c:1131
struct ast_cc_config_params * config_params
Definition: ccss.h:817
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1108
#define ast_free(a)
Definition: astmm.h:97
struct ast_cc_interface * interface
Definition: ccss.h:497
private data for generic device monitor
Definition: ccss.c:1079
#define ast_calloc(a, b)
Definition: astmm.h:82
int ast_sched_thread_add(struct ast_sched_thread *st, int when, ast_sched_cb cb, const void *data)
Add a scheduler entry.
Definition: sched.c:210
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:544
char device_name[1]
Definition: ccss.h:822
const char * device_name
Definition: ccss.c:1084
enum ast_cc_service_type service_offered
Definition: ccss.h:515
static int cc_generic_monitor_suspend ( struct ast_cc_monitor monitor)
static

Definition at line 1312 of file ccss.c.

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

1313 {
1314  struct generic_monitor_instance_list *generic_list;
1315  struct generic_monitor_instance *generic_instance;
1317 
1318  if (!(generic_list = find_generic_monitor_instance_list(monitor->interface->device_name))) {
1319  return -1;
1320  }
1321 
1322  /* First we need to mark this particular monitor as being suspended. */
1323  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1324  if (generic_instance->core_id == monitor->core_id) {
1325  generic_instance->is_suspended = 1;
1326  break;
1327  }
1328  }
1329 
1330  /* If the device being suspended is currently in use, then we don't need to
1331  * take any further actions
1332  */
1333  if (!cc_generic_is_device_available(state)) {
1334  cc_unref(generic_list, "Device is in use. Nothing to do. Unref generic list.");
1335  return 0;
1336  }
1337 
1338  /* If the device is not in use, though, then it may be possible to report the
1339  * device's availability using a different monitor which is monitoring the
1340  * same device
1341  */
1342 
1343  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1344  if (!generic_instance->is_suspended) {
1345  ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1346  break;
1347  }
1348  }
1349  cc_unref(generic_list, "Done with generic list in suspend callback");
1350  return 0;
1351 }
ast_device_state
Device States.
Definition: devicestate.h:51
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
struct generic_monitor_instance_list::@233 list
int core_id
Definition: ccss.h:511
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1108
#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:497
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1024
char device_name[1]
Definition: ccss.h:822
struct generic_monitor_instance * next
Definition: ccss.c:1050
int ast_cc_monitor_callee_available(const int core_id, const char *const debug,...)
Alert the core that a device being monitored has become available.
Definition: ccss.c:3532
static int cc_generic_monitor_unsuspend ( struct ast_cc_monitor monitor)
static

Definition at line 1353 of file ccss.c.

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

1354 {
1355  struct generic_monitor_instance *generic_instance;
1358 
1359  if (!generic_list) {
1360  return -1;
1361  }
1362  /* If the device is currently available, we can immediately announce
1363  * its availability
1364  */
1365  if (cc_generic_is_device_available(state)) {
1366  ast_cc_monitor_callee_available(monitor->core_id, "Generic monitored party has become available");
1367  }
1368 
1369  /* In addition, we need to mark this generic_monitor_instance as not being suspended anymore */
1370  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1371  if (generic_instance->core_id == monitor->core_id) {
1372  generic_instance->is_suspended = 0;
1373  generic_instance->monitoring = 1;
1374  break;
1375  }
1376  }
1377  cc_unref(generic_list, "Done with generic list in cc_generic_monitor_unsuspend");
1378  return 0;
1379 }
ast_device_state
Device States.
Definition: devicestate.h:51
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
struct generic_monitor_instance_list::@233 list
int core_id
Definition: ccss.h:511
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1108
#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:497
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1024
char device_name[1]
Definition: ccss.h:822
int ast_cc_monitor_callee_available(const int core_id, const char *const debug,...)
Alert the core that a device being monitored has become available.
Definition: ccss.c:3532
static void cc_interface_destroy ( void *  data)
static

Definition at line 1467 of file ccss.c.

References ast_cc_config_params_destroy(), and ast_log_dynamic_level.

Referenced by cc_device_monitor_init(), and cc_extension_monitor_init().

1468 {
1469  struct ast_cc_interface *interface = data;
1470  ast_log_dynamic_level(cc_logger_level, "Destroying cc interface %s\n", interface->device_name);
1471  ast_cc_config_params_destroy(interface->config_params);
1472 }
void ast_cc_config_params_destroy(struct ast_cc_config_params *params)
Free memory from CCSS configuration params.
Definition: ccss.c:579
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
Structure with information about an outbound interface.
Definition: ccss.h:801
static int cc_logger_level
Definition: ccss.c:124
static void cc_interface_tree_destroy ( void *  data)
static

Definition at line 1588 of file ccss.c.

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

Referenced by cc_interfaces_datastore_init().

1589 {
1590  struct cc_monitor_tree *cc_interface_tree = data;
1591  struct ast_cc_monitor *monitor;
1592  while ((monitor = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
1593  if (monitor->callbacks) {
1594  monitor->callbacks->cancel_available_timer(monitor, &monitor->available_timer_id);
1595  }
1596  cc_unref(monitor, "Destroying all monitors");
1597  }
1598  AST_LIST_HEAD_DESTROY(cc_interface_tree);
1599 }
struct ast_cc_monitor * next
Definition: ccss.h:545
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:638
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
static unsigned int monitor
Definition: chan_phone.c:108
The &quot;tree&quot; of interfaces that is dialed.
Definition: ccss.c:314
int(* cancel_available_timer)(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
Definition: ccss.h:640
int available_timer_id
Definition: ccss.h:530
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:534
static int cc_interfaces_datastore_init ( struct ast_channel chan)
static

Definition at line 1868 of file ccss.c.

References ao2_t_alloc, ast_atomic_fetchadd_int(), ast_calloc, ast_cc_request_is_within_limits(), ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc(), ast_datastore_free(), ast_free, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, cc_extension_monitor_init(), cc_interface_tree_destroy(), cc_ref(), cc_unref(), ast_channel::context, ast_cc_monitor::core_id, dialed_cc_interfaces::core_id, ast_datastore::data, DATASTORE_INHERIT_FOREVER, dialed_cc_interfaces::dial_parent_id, ast_channel::exten, ast_cc_monitor::id, ast_datastore::inheritance, dialed_cc_interfaces::interface_tree, dialed_cc_interfaces::is_original_caller, ast_channel::macrocontext, ast_channel::macroexten, monitor, and S_OR.

Referenced by ast_cc_call_init().

1868  {
1869  struct dialed_cc_interfaces *interfaces;
1870  struct ast_cc_monitor *monitor;
1871  struct ast_datastore *dial_cc_datastore;
1872 
1873  /*XXX This may be a bit controversial. In an attempt to not allocate
1874  * extra resources, I make sure that a future request will be within
1875  * limits. The problem here is that it is reasonable to think that
1876  * even if we're not within the limits at this point, we may be by
1877  * the time the requestor will have made his request. This may be
1878  * deleted at some point.
1879  */
1881  return 0;
1882  }
1883 
1884  if (!(interfaces = ast_calloc(1, sizeof(*interfaces)))) {
1885  return -1;
1886  }
1887 
1888  if (!(monitor = cc_extension_monitor_init(S_OR(chan->macroexten, chan->exten), S_OR(chan->macrocontext, chan->context), 0))) {
1889  ast_free(interfaces);
1890  return -1;
1891  }
1892 
1893  if (!(dial_cc_datastore = ast_datastore_alloc(&dialed_cc_interfaces_info, NULL))) {
1894  cc_unref(monitor, "Could not allocate the dialed interfaces datastore. Unreffing monitor");
1895  ast_free(interfaces);
1896  return -1;
1897  }
1898 
1899  if (!(interfaces->interface_tree = ao2_t_alloc(sizeof(*interfaces->interface_tree), cc_interface_tree_destroy,
1900  "Allocate monitor tree"))) {
1901  ast_datastore_free(dial_cc_datastore);
1902  cc_unref(monitor, "Could not allocate monitor tree on dialed interfaces datastore. Unreffing monitor");
1903  ast_free(interfaces);
1904  return -1;
1905  }
1906 
1907  /* Finally, all that allocation is done... */
1908  AST_LIST_HEAD_INIT(interfaces->interface_tree);
1909  AST_LIST_INSERT_TAIL(interfaces->interface_tree, monitor, next);
1910  cc_ref(monitor, "List's reference to extension monitor");
1911  dial_cc_datastore->data = interfaces;
1912  dial_cc_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
1913  interfaces->dial_parent_id = monitor->id;
1914  interfaces->core_id = monitor->core_id = ast_atomic_fetchadd_int(&core_id_counter, +1);
1915  interfaces->is_original_caller = 1;
1916  ast_channel_lock(chan);
1917  ast_channel_datastore_add(chan, dial_cc_datastore);
1918  ast_channel_unlock(chan);
1919  cc_unref(monitor, "Unreffing allocation's reference");
1920  return 0;
1921 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
struct ast_datastore * next
Definition: datastore.h:59
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:429
unsigned int id
Definition: ccss.h:502
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
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:1819
Structure for a data store object.
Definition: datastore.h:54
static int core_id_counter
Definition: ccss.c:111
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
static void cc_interface_tree_destroy(void *data)
Definition: ccss.c:1588
int core_id
Definition: ccss.h:511
char is_original_caller
Definition: ccss.c:1655
static struct ast_datastore_info dialed_cc_interfaces_info
Definition: ccss.c:1719
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
static unsigned int monitor
Definition: chan_phone.c:108
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:611
#define ast_free(a)
Definition: astmm.h:97
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:156
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:2219
unsigned int inheritance
Definition: datastore.h:58
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1659
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
void * data
Definition: datastore.h:56
#define ast_calloc(a, b)
Definition: astmm.h:82
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
unsigned int dial_parent_id
Definition: ccss.c:1632
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static void cc_monitor_destroy ( void *  data)
static

Definition at line 1567 of file ccss.c.

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

Referenced by cc_device_monitor_init(), and cc_extension_monitor_init().

1568 {
1569  struct ast_cc_monitor *monitor = data;
1570  /* During the monitor creation process, it is possible for this
1571  * function to be called prior to when callbacks are assigned
1572  * to the monitor. Also, extension monitors do not have callbacks
1573  * assigned to them, so we wouldn't want to segfault when we try
1574  * to destroy one of them.
1575  */
1576  ast_log_dynamic_level(cc_logger_level, "Core %d: Calling destructor for monitor %s\n",
1577  monitor->core_id, monitor->interface->device_name);
1580  }
1581  if (monitor->callbacks) {
1582  monitor->callbacks->destructor(monitor->private_data);
1583  }
1584  cc_unref(monitor->interface, "Unreffing tree's reference to interface");
1585  ast_free(monitor->dialstring);
1586 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
static void cc_extension_monitor_destructor(void *private_data)
Definition: ccss.c:1551
int core_id
Definition: ccss.h:511
static unsigned int monitor
Definition: chan_phone.c:108
#define ast_free(a)
Definition: astmm.h:97
char * dialstring
Name that should be used to recall specified interface.
Definition: ccss.h:526
void(* destructor)(void *private_data)
Destroy private data on the monitor.
Definition: ccss.h:651
struct ast_cc_interface * interface
Definition: ccss.h:497
void * private_data
Data that is private to a monitor technology.
Definition: ccss.h:544
char device_name[1]
Definition: ccss.h:822
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:534
static int cc_logger_level
Definition: ccss.c:124
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
static int cc_monitor_failed ( void *  data)
static

Definition at line 3630 of file ccss.c.

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

Referenced by ast_cc_monitor_failed().

3631 {
3632  struct ast_cc_monitor_failure_data *failure_data = data;
3633  struct cc_core_instance *core_instance;
3634  struct ast_cc_monitor *monitor_iter;
3635 
3636  core_instance = find_cc_core_instance(failure_data->core_id);
3637  if (!core_instance) {
3638  /* Core instance no longer exists or invalid core_id. */
3640  "Core %d: Could not find core instance for device %s '%s'\n",
3641  failure_data->core_id, failure_data->device_name, failure_data->debug);
3642  ast_free((char *) failure_data->device_name);
3643  ast_free((char *) failure_data->debug);
3644  ast_free(failure_data);
3645  return -1;
3646  }
3647 
3648  AST_LIST_LOCK(core_instance->monitors);
3649  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
3650  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
3651  if (!strcmp(monitor_iter->interface->device_name, failure_data->device_name)) {
3653  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
3654  monitor_iter->interface->device_name, 1);
3655  monitor_iter->callbacks->cancel_available_timer(monitor_iter, &monitor_iter->available_timer_id);
3656  manager_event(EVENT_FLAG_CC, "CCMonitorFailed",
3657  "CoreID: %d\r\n"
3658  "Callee: %s\r\n",
3659  monitor_iter->core_id, monitor_iter->interface->device_name);
3660  cc_unref(monitor_iter, "Monitor reported failure. Unref list's reference.");
3661  }
3662  }
3663  }
3665 
3666  if (!has_device_monitors(core_instance)) {
3667  ast_cc_failed(core_instance->core_id, "All monitors have failed\n");
3668  }
3669  AST_LIST_UNLOCK(core_instance->monitors);
3670  cc_unref(core_instance, "Finished with core_instance in cc_monitor_failed\n");
3671 
3672  ast_free((char *) failure_data->device_name);
3673  ast_free((char *) failure_data->debug);
3674  ast_free(failure_data);
3675  return 0;
3676 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
struct ast_cc_monitor * next
Definition: ccss.h:545
#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:3613
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:421
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
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:1780
#define EVENT_FLAG_CC
Definition: manager.h:86
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
unsigned int parent_id
Definition: ccss.h:507
const char * device_name
Definition: ccss.c:3625
int core_id
Definition: ccss.h:511
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
#define ast_free(a)
Definition: astmm.h:97
struct ast_cc_interface * interface
Definition: ccss.h:497
int(* cancel_available_timer)(struct ast_cc_monitor *monitor, int *sched_id)
Cancel the running available timer.
Definition: ccss.h:640
int available_timer_id
Definition: ccss.h:530
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:2809
#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:822
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:534
static int cc_logger_level
Definition: ccss.c:124
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
static int cc_offer ( const int  core_id,
const char *const  debug,
  ... 
)
static

Definition at line 3474 of file ccss.c.

References CC_CALLER_OFFERED, and cc_request_state_change().

Referenced by ast_cc_offer().

3475 {
3476  va_list ap;
3477  int res;
3478 
3479  va_start(ap, debug);
3481  va_end(ap);
3482  return res;
3483 }
int core_id
Definition: ccss.h:511
static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug, va_list ap)
Definition: ccss.c:3062
static int cc_party_b_free ( void *  data)
static

Definition at line 3776 of file ccss.c.

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

Referenced by ast_cc_monitor_party_b_free().

3777 {
3778  struct cc_core_instance *core_instance = data;
3779  int res = 0;
3780 
3781  if (core_instance->agent->callbacks->party_b_free) {
3782  res = core_instance->agent->callbacks->party_b_free(core_instance->agent);
3783  }
3784  cc_unref(core_instance, "Party B free finished. Unref core_instance");
3785  return res;
3786 }
int(* party_b_free)(struct ast_cc_agent *agent)
Let the caller know that the callee has become free but that the caller cannot attempt to call back b...
Definition: ccss.h:1006
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
struct ast_cc_agent * agent
Definition: ccss.c:331
static void cc_recall_ds_destroy ( void *  data)
static

Definition at line 3126 of file ccss.c.

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

3127 {
3128  struct cc_recall_ds_data *recall_data = data;
3129  recall_data->interface_tree = cc_unref(recall_data->interface_tree, "Unref recall monitor tree");
3130  ast_free(recall_data);
3131 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define ast_free(a)
Definition: astmm.h:97
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3109
static void* cc_recall_ds_duplicate ( void *  data)
static

Definition at line 3112 of file ccss.c.

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

3113 {
3114  struct cc_recall_ds_data *old_data = data;
3115  struct cc_recall_ds_data *new_data = ast_calloc(1, sizeof(*new_data));
3116 
3117  if (!new_data) {
3118  return NULL;
3119  }
3120  new_data->interface_tree = cc_ref(old_data->interface_tree, "Bump refcount of monitor tree for recall datastore duplicate");
3121  new_data->core_id = old_data->core_id;
3122  new_data->nested = 1;
3123  return new_data;
3124 }
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
#define ast_calloc(a, b)
Definition: astmm.h:82
struct cc_monitor_tree * interface_tree
Definition: ccss.c:3109
static int cc_recalling ( struct cc_core_instance core_instance,
struct cc_state_change_args args,
enum cc_state  previous_state 
)
static

Definition at line 2977 of file ccss.c.

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

2978 {
2979  /* Both caller and callee are available, call agent's recall callback
2980  */
2981  cancel_available_timer(core_instance);
2982  manager_event(EVENT_FLAG_CC, "CCCallerRecalling",
2983  "CoreID: %d\r\n"
2984  "Caller: %s\r\n",
2985  core_instance->core_id, core_instance->agent->device_name);
2986  return 0;
2987 }
#define EVENT_FLAG_CC
Definition: manager.h:86
static void cancel_available_timer(struct cc_core_instance *core_instance)
Definition: ccss.c:2955
char device_name[1]
Definition: ccss.h:858
struct ast_cc_agent * agent
Definition: ccss.c:331
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
static void* cc_ref ( void *  obj,
const char *  debug 
)
inlinestatic
static int cc_request_state_change ( enum cc_state  state,
const int  core_id,
const char *  debug,
va_list  ap 
)
static

Definition at line 3062 of file ccss.c.

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

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

3063 {
3064  int res;
3065  int debuglen;
3066  char dummy[1];
3067  va_list aq;
3068  struct cc_core_instance *core_instance;
3069  struct cc_state_change_args *args;
3070  /* This initial call to vsnprintf is simply to find what the
3071  * size of the string needs to be
3072  */
3073  va_copy(aq, ap);
3074  /* We add 1 to the result since vsnprintf's return does not
3075  * include the terminating null byte
3076  */
3077  debuglen = vsnprintf(dummy, sizeof(dummy), debug, aq) + 1;
3078  va_end(aq);
3079 
3080  if (!(args = ast_calloc(1, sizeof(*args) + debuglen))) {
3081  return -1;
3082  }
3083 
3084  core_instance = find_cc_core_instance(core_id);
3085  if (!core_instance) {
3086  ast_log_dynamic_level(cc_logger_level, "Core %d: Unable to find core instance.\n",
3087  core_id);
3088  ast_free(args);
3089  return -1;
3090  }
3091 
3092  args->core_instance = core_instance;
3093  args->state = state;
3094  args->core_id = core_id;
3095  vsnprintf(args->debug, debuglen, debug, ap);
3096 
3098  if (res) {
3099  cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
3100  ast_free(args);
3101  }
3102  return res;
3103 }
enum sip_cc_notify_state state
Definition: chan_sip.c:842
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static struct cc_core_instance * find_cc_core_instance(const int core_id)
Definition: ccss.c:421
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
enum cc_state state
Definition: ccss.c:2708
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
struct cc_core_instance * core_instance
Definition: ccss.c:2707
static int cc_do_state_change(void *datap)
Definition: ccss.c:3024
static struct @350 args
#define ast_free(a)
Definition: astmm.h:97
#define ast_calloc(a, b)
Definition: astmm.h:82
static int cc_logger_level
Definition: ccss.c:124
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
static const char* cc_service_to_string ( enum ast_cc_service_type  service)
static

Definition at line 402 of file ccss.c.

References cc_service_to_string_map, and service.

Referenced by ast_handle_cc_control_frame(), and cc_cli_print_monitor_stats().

403 {
404  return cc_service_to_string_map[service].service_string;
405 }
enum ast_cc_service_type service
Definition: chan_sip.c:821
static struct @228 cc_service_to_string_map[]
static void cc_shutdown ( void  )
static

Definition at line 4313 of file ccss.c.

References ao2_t_ref, ARRAY_LEN, ast_cc_agent_unregister(), ast_cc_monitor_unregister(), ast_cli_unregister_multiple(), ast_devstate_prov_del(), ast_logger_unregister_level(), ast_sched_thread_destroy(), ast_taskprocessor_unreference(), ast_unregister_application(), generic_monitor_cbs, and generic_monitors.

Referenced by ast_cc_init().

4314 {
4315  ast_devstate_prov_del("ccss");
4322 
4323  if (cc_sched_thread) {
4325  }
4326  if (cc_core_taskprocessor) {
4328  }
4329  /* Note that cc_core_instances must be disposed of prior to generic_monitors */
4330  if (cc_core_instances) {
4331  ao2_t_ref(cc_core_instances, -1, "Unref cc_core_instances container in cc_shutdown");
4332  cc_core_instances = NULL;
4333  }
4334  if (generic_monitors) {
4335  ao2_t_ref(generic_monitors, -1, "Unref generic_monitor container in cc_shutdown");
4336  generic_monitors = NULL;
4337  }
4338 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:471
void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks)
Unregister a set of agent callbacks with the core.
Definition: ccss.c:965
struct ast_sched_thread * ast_sched_thread_destroy(struct ast_sched_thread *st)
Destroy a scheduler and its thread.
Definition: sched.c:143
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static struct ast_sched_thread * cc_sched_thread
Definition: ccss.c:106
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:389
static const char * ccreq_app
Definition: ccss.c:3992
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static const char * CC_LOGGER_LEVEL_NAME
Definition: ccss.c:120
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:1670
static struct ast_cli_entry cc_cli[]
Definition: ccss.c:4308
struct ao2_container * generic_monitors
Definition: ccss.c:1044
static struct ast_cc_agent_callbacks generic_agent_callbacks
Definition: ccss.c:2343
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
static struct ast_cc_monitor_callbacks generic_monitor_cbs
Definition: ccss.c:1035
void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks)
Unregister a set of monitor callbacks with the core.
Definition: ccss.c:928
static const char * cccancel_app
Definition: ccss.c:4043
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
static const char* cc_state_to_string ( enum cc_state  state)
static

Definition at line 397 of file ccss.c.

References cc_state_to_string_map, and state.

Referenced by cc_do_state_change(), and print_stats_cb().

398 {
399  return cc_state_to_string_map[state].state_string;
400 }
enum sip_cc_notify_state state
Definition: chan_sip.c:842
static struct @229 cc_state_to_string_map[]
static int cc_status_request ( void *  data)
static

Definition at line 3713 of file ccss.c.

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

Referenced by ast_cc_monitor_status_request().

3714 {
3715  struct cc_core_instance *core_instance= data;
3716  int res;
3717 
3718  res = core_instance->agent->callbacks->status_request(core_instance->agent);
3719  cc_unref(core_instance, "Status request finished. Unref core instance");
3720  return res;
3721 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
int(* status_request)(struct ast_cc_agent *agent)
Request the status of the agent&#39;s device.
Definition: ccss.h:963
struct ast_cc_agent * agent
Definition: ccss.c:331
static int cc_status_response ( void *  data)
static

Definition at line 3809 of file ccss.c.

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

Referenced by ast_cc_agent_status_response().

3810 {
3811  struct cc_status_response_args *args = data;
3812  struct cc_core_instance *core_instance = args->core_instance;
3813  struct ast_cc_monitor *monitor_iter;
3814  enum ast_device_state devstate = args->devstate;
3815 
3816  ast_free(args);
3817 
3818  AST_LIST_LOCK(core_instance->monitors);
3819  AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
3820  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR &&
3821  monitor_iter->callbacks->status_response) {
3822  monitor_iter->callbacks->status_response(monitor_iter, devstate);
3823  }
3824  }
3825  AST_LIST_UNLOCK(core_instance->monitors);
3826  cc_unref(core_instance, "Status response finished. Unref core instance");
3827  return 0;
3828 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
struct ast_cc_monitor * next
Definition: ccss.h:545
ast_device_state
Device States.
Definition: devicestate.h:51
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int(* status_response)(struct ast_cc_monitor *monitor, enum ast_device_state devstate)
Status response to an ast_cc_monitor_status_request().
Definition: ccss.h:611
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static struct @350 args
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct cc_core_instance * core_instance
Definition: ccss.c:3805
#define ast_free(a)
Definition: astmm.h:97
struct ast_cc_interface * interface
Definition: ccss.h:497
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:534
enum ast_device_state devstate
Definition: ccss.c:3806
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
static int cc_stop_ringing ( void *  data)
static

Definition at line 3739 of file ccss.c.

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

Referenced by ast_cc_monitor_stop_ringing().

3740 {
3741  struct cc_core_instance *core_instance = data;
3742  int res = 0;
3743 
3744  if (core_instance->agent->callbacks->stop_ringing) {
3745  res = core_instance->agent->callbacks->stop_ringing(core_instance->agent);
3746  }
3747  /* If an agent is being asked to stop ringing, then he needs to be prepared if for
3748  * whatever reason he needs to be called back again. The proper state to be in to
3749  * detect such a circumstance is the CC_ACTIVE state.
3750  *
3751  * We get to this state using the slightly unintuitive method of calling
3752  * ast_cc_monitor_request_acked because it gets us to the proper state.
3753  */
3754  ast_cc_monitor_request_acked(core_instance->core_id, "Agent %s asked to stop ringing. Be prepared to be recalled again.",
3755  core_instance->agent->device_name);
3756  cc_unref(core_instance, "Stop ringing finished. Unref core_instance");
3757  return res;
3758 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
int ast_cc_monitor_request_acked(int core_id, const char *const debug,...)
Indicate that an outbound entity has accepted our CC request.
Definition: ccss.c:3521
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
char device_name[1]
Definition: ccss.h:858
int(* stop_ringing)(struct ast_cc_agent *agent)
Request for an agent&#39;s phone to stop ringing.
Definition: ccss.h:985
struct ast_cc_agent * agent
Definition: ccss.c:331
static void cc_unique_append ( struct ast_str **  str,
const char *  dialstring 
)
static

Definition at line 3292 of file ccss.c.

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

Referenced by build_cc_interfaces_chanvar().

3293 {
3294  char dialstring_search[AST_CHANNEL_NAME];
3295 
3296  if (ast_strlen_zero(dialstring)) {
3297  /* No dialstring to append. */
3298  return;
3299  }
3300  snprintf(dialstring_search, sizeof(dialstring_search), "%s%c", dialstring, '&');
3301  if (strstr(ast_str_buffer(*str), dialstring_search)) {
3302  return;
3303  }
3304  ast_str_append(str, 0, "%s", dialstring_search);
3305 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_CHANNEL_NAME
Definition: channel.h:137
static void* cc_unref ( void *  obj,
const char *  debug 
)
inlinestatic
static int cccancel_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 4045 of file ccss.c.

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

Referenced by ast_cc_init().

4046 {
4047  struct cc_core_instance *core_instance;
4048  char device_name[AST_CHANNEL_NAME];
4049  unsigned long match_flags;
4050  int res;
4051 
4052  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4053 
4054  match_flags = MATCH_REQUEST;
4055  if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) {
4056  ast_log_dynamic_level(cc_logger_level, "Cannot find CC transaction to cancel for caller %s\n", device_name);
4057  pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4058  pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NO_CORE_INSTANCE");
4059  return 0;
4060  }
4061 
4062  if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4063  ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calles with a generic agent\n");
4064  cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4065  pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
4066  pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NOT_GENERIC");
4067  return 0;
4068  }
4069  res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s",
4070  core_instance->core_id, device_name);
4071  cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
4072  pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", res ? "FAIL" : "SUCCESS");
4073  if (res) {
4074  pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "UNSPECIFIED");
4075  }
4076  return 0;
4077 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3613
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define LOG_WARNING
Definition: logger.h:144
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define ao2_t_callback_data(arg1, arg2, arg3, arg4, arg5, arg6)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container...
Definition: astobj2.h:942
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:877
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
match_flags
Definition: ccss.c:459
#define AST_CHANNEL_NAME
Definition: channel.h:137
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:482
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...
Definition: pbx.c:10546
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
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:9776
struct ast_cc_agent * agent
Definition: ccss.c:331
static int cc_logger_level
Definition: ccss.c:124
static int ccreq_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 3994 of file ccss.c.

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

Referenced by ast_cc_init().

3995 {
3996  struct cc_core_instance *core_instance;
3997  char device_name[AST_CHANNEL_NAME];
3998  unsigned long match_flags;
3999  int res;
4000 
4001  ast_channel_get_device_name(chan, device_name, sizeof(device_name));
4002 
4003  match_flags = MATCH_NO_REQUEST;
4004  if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) {
4005  ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name);
4006  pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4007  pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NO_CORE_INSTANCE");
4008  return 0;
4009  }
4010 
4011  ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n",
4012  core_instance->core_id, device_name);
4013 
4014  if (strcmp(core_instance->agent->callbacks->type, "generic")) {
4015  ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n",
4016  core_instance->core_id);
4017  pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4018  pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NOT_GENERIC");
4019  cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent");
4020  return 0;
4021  }
4022 
4024  ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest failed. Too many requests in the system\n",
4025  core_instance->core_id);
4026  ast_cc_failed(core_instance->core_id, "Too many CC requests\n");
4027  pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
4028  pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "TOO_MANY_REQUESTS");
4029  cc_unref(core_instance, "Unref core_instance since too many CC requests");
4030  return 0;
4031  }
4032 
4033  res = ast_cc_agent_accept_request(core_instance->core_id, "CallCompletionRequest called by caller %s for core_id %d", device_name, core_instance->core_id);
4034  pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS");
4035  if (res) {
4036  pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "UNSPECIFIED");
4037  }
4038 
4039  cc_unref(core_instance, "Done with CallCompletionRequest");
4040  return 0;
4041 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3613
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define ao2_t_callback_data(arg1, arg2, arg3, arg4, arg5, arg6)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container...
Definition: astobj2.h:942
int ast_cc_agent_accept_request(int core_id, const char *const debug,...)
Accept inbound CC request.
Definition: ccss.c:3510
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.h:837
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:877
match_flags
Definition: ccss.c:459
#define AST_CHANNEL_NAME
Definition: channel.h:137
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:482
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:2219
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...
Definition: pbx.c:10546
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
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:9776
struct ast_cc_agent * agent
Definition: ccss.c:331
static int cc_logger_level
Definition: ccss.c:124
static void check_callback_sanity ( const struct ast_cc_agent_callbacks callbacks)
static

Definition at line 2269 of file ccss.c.

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

Referenced by cc_agent_init().

2270 {
2271  ast_assert(callbacks->init != NULL);
2272  ast_assert(callbacks->start_offer_timer != NULL);
2273  ast_assert(callbacks->stop_offer_timer != NULL);
2274  ast_assert(callbacks->respond != NULL);
2275  ast_assert(callbacks->status_request != NULL);
2276  ast_assert(callbacks->start_monitoring != NULL);
2277  ast_assert(callbacks->callee_available != NULL);
2278  ast_assert(callbacks->destructor != NULL);
2279 }
int(* init)(struct ast_cc_agent *agent, struct ast_channel *chan)
CC agent initialization.
Definition: ccss.h:896
#define ast_assert(a)
Definition: utils.h:738
int(* stop_offer_timer)(struct ast_cc_agent *agent)
Stop the offer timer.
Definition: ccss.h:930
int(* callee_available)(struct ast_cc_agent *agent)
Alert the caller that it is time to try recalling.
Definition: ccss.h:1041
void(* destructor)(struct ast_cc_agent *agent)
Destroy private data on the agent.
Definition: ccss.h:1055
int(* start_monitoring)(struct ast_cc_agent *agent)
Begin monitoring a busy device.
Definition: ccss.h:1022
int(* start_offer_timer)(struct ast_cc_agent *agent)
Start the offer timer.
Definition: ccss.h:917
int(* status_request)(struct ast_cc_agent *agent)
Request the status of the agent&#39;s device.
Definition: ccss.h:963
void(* respond)(struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
Respond to a CC request.
Definition: ccss.h:948
static char* complete_core_id ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 4239 of file ccss.c.

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

Referenced by handle_cc_kill().

4240 {
4241  int which = 0;
4242  int wordlen = strlen(word);
4243  char *ret = NULL;
4244  struct ao2_iterator core_iter = ao2_iterator_init(cc_core_instances, 0);
4245  struct cc_core_instance *core_instance;
4246 
4247  for (; (core_instance = ao2_t_iterator_next(&core_iter, "Next core instance"));
4248  cc_unref(core_instance, "CLI tab completion iteration")) {
4249  char core_id_str[20];
4250  snprintf(core_id_str, sizeof(core_id_str), "%d", core_instance->core_id);
4251  if (!strncmp(word, core_id_str, wordlen) && ++which > state) {
4252  ret = ast_strdup(core_id_str);
4253  cc_unref(core_instance, "Found a matching core ID for CLI tab-completion");
4254  break;
4255  }
4256  }
4257  ao2_iterator_destroy(&core_iter);
4258 
4259  return ret;
4260 }
#define ast_strdup(a)
Definition: astmm.h:109
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define ao2_t_iterator_next(arg1, arg2)
Definition: astobj2.h:1125
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
Definition: ael.tab.c:203
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
static long count_agents ( const char *const  caller,
const int  core_id_exception 
)
static

Definition at line 2243 of file ccss.c.

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

Referenced by agents_show(), agents_show_online(), and cc_core_init_instance().

2244 {
2246 
2247  ao2_t_callback_data(cc_core_instances, OBJ_NODATA, count_agents_cb, (char *)caller, &data, "Counting agents");
2248  ast_log_dynamic_level(cc_logger_level, "Counted %d agents\n", data.count);
2249  return data.count;
2250 }
static int count_agents_cb(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:520
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define ao2_t_callback_data(arg1, arg2, arg3, arg4, arg5, arg6)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container...
Definition: astobj2.h:942
int core_id_exception
Definition: ccss.c:509
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
static int cc_logger_level
Definition: ccss.c:124
static int count_agents_cb ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 520 of file ccss.c.

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

Referenced by count_agents().

521 {
522  struct cc_core_instance *core_instance = obj;
523  const char *name = arg;
524  struct count_agents_cb_data *cb_data = data;
525 
526  if (cb_data->core_id_exception == core_instance->core_id) {
527  ast_log_dynamic_level(cc_logger_level, "Found agent with core_id %d but not counting it toward total\n", core_instance->core_id);
528  return 0;
529  }
530 
531  if (core_instance->current_state >= CC_CALLER_REQUESTED && !strcmp(core_instance->agent->device_name, name)) {
532  cb_data->count++;
533  }
534  return 0;
535 }
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
int core_id_exception
Definition: ccss.c:509
enum cc_state current_state
Definition: ccss.c:327
static const char name[]
char device_name[1]
Definition: ccss.h:858
struct ast_cc_agent * agent
Definition: ccss.c:331
static int cc_logger_level
Definition: ccss.c:124
static int count_monitors_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 4085 of file ccss.c.

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

Referenced by ast_cc_monitor_count().

4086 {
4087  struct cc_core_instance *core_instance = obj;
4088  struct count_monitors_cb_data *cb_data = arg;
4089  const char *device_name = cb_data->device_name;
4090  const char *monitor_type = cb_data->monitor_type;
4091  struct ast_cc_monitor *monitor_iter;
4092 
4093  AST_LIST_LOCK(core_instance->monitors);
4094  AST_LIST_TRAVERSE(core_instance->monitors, monitor_iter, next) {
4095  if (!strcmp(monitor_iter->interface->device_name, device_name) &&
4096  !strcmp(monitor_iter->interface->monitor_type, monitor_type)) {
4097  cb_data->count++;
4098  break;
4099  }
4100  }
4101  AST_LIST_UNLOCK(core_instance->monitors);
4102  return 0;
4103 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
struct ast_cc_monitor * next
Definition: ccss.h:545
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
const char * monitor_type
Definition: ccss.c:4081
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
const char * monitor_type
The type of monitor that should be used for this interface.
Definition: ccss.h:813
struct ast_cc_interface * interface
Definition: ccss.h:497
char device_name[1]
Definition: ccss.h:822
const char * device_name
Definition: ccss.c:4080
static struct generic_monitor_instance_list* create_new_generic_list ( struct ast_cc_monitor monitor)
static

Definition at line 1131 of file ccss.c.

References ao2_t_alloc, ao2_t_link, AST_EVENT_DEVICE_STATE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_STATE, ast_event_subscribe(), ast_strdup, ast_tech_to_upper(), cc_unref(), generic_monitor_instance_list::current_state, ast_cc_interface::device_name, generic_monitor_instance_list::device_name, generic_monitor_devstate_cb(), generic_monitor_instance_list_destructor(), generic_monitors, ast_cc_monitor::interface, and generic_monitor_instance_list::sub.

Referenced by cc_generic_monitor_request_cc().

1132 {
1133  struct generic_monitor_instance_list *generic_list = ao2_t_alloc(sizeof(*generic_list),
1134  generic_monitor_instance_list_destructor, "allocate generic monitor instance list");
1135  char * device_name;
1136 
1137  if (!generic_list) {
1138  return NULL;
1139  }
1140 
1141  if (!(device_name = ast_strdup(monitor->interface->device_name))) {
1142  cc_unref(generic_list, "Failed to strdup the monitor's device name");
1143  return NULL;
1144  }
1145  ast_tech_to_upper(device_name);
1146  generic_list->device_name = device_name;
1147 
1148  if (!(generic_list->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE,
1149  generic_monitor_devstate_cb, "Requesting CC", NULL,
1152  AST_EVENT_IE_END))) {
1153  cc_unref(generic_list, "Failed to subscribe to device state");
1154  return NULL;
1155  }
1156  generic_list->current_state = ast_device_state(monitor->interface->device_name);
1157  ao2_t_link(generic_monitors, generic_list, "linking new generic monitor instance list");
1158  return generic_list;
1159 }
ast_device_state
Device States.
Definition: devicestate.h:51
#define ast_strdup(a)
Definition: astmm.h:109
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:429
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
static void generic_monitor_instance_list_destructor(void *obj)
Definition: ccss.c:1118
#define ao2_t_link(arg1, arg2, arg3)
Add an object to a container.
Definition: astobj2.h:784
struct ast_event_sub * sub
Definition: ccss.c:1072
struct ao2_container * generic_monitors
Definition: ccss.c:1044
char * ast_tech_to_upper(char *dev_str)
Convert the tech portion of a device string to upper case.
Definition: strings.h:939
struct ast_cc_interface * interface
Definition: ccss.h:497
static void generic_monitor_devstate_cb(const struct ast_event *event, void *userdata)
Definition: ccss.c:1214
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
Definition: event.c:909
char device_name[1]
Definition: ccss.h:822
Generic State IE Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: UINT The actual state values dep...
Definition: event_defs.h:115
enum ast_device_state current_state
Definition: ccss.c:1055
const char * device_name
Definition: ccss.c:1054
Device Name Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: STR.
Definition: event_defs.h:107
static void dialed_cc_interfaces_destroy ( void *  data)
static

Definition at line 1674 of file ccss.c.

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

1675 {
1676  struct dialed_cc_interfaces *cc_interfaces = data;
1677  cc_unref(cc_interfaces->interface_tree, "Unref dial's ref to monitor tree");
1678  ast_free(cc_interfaces);
1679 }
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define ast_free(a)
Definition: astmm.h:97
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1659
static void* dialed_cc_interfaces_duplicate ( void *  data)
static

Definition at line 1694 of file ccss.c.

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

1695 {
1696  struct dialed_cc_interfaces *old_cc_interfaces = data;
1697  struct dialed_cc_interfaces *new_cc_interfaces = ast_calloc(1, sizeof(*new_cc_interfaces));
1698  if (!new_cc_interfaces) {
1699  return NULL;
1700  }
1701  new_cc_interfaces->ignore = old_cc_interfaces->ignore;
1702  new_cc_interfaces->dial_parent_id = old_cc_interfaces->dial_parent_id;
1703  new_cc_interfaces->is_original_caller = 0;
1704  cc_ref(old_cc_interfaces->interface_tree, "New ref due to duplication of monitor tree");
1705  new_cc_interfaces->core_id = old_cc_interfaces->core_id;
1706  new_cc_interfaces->interface_tree = old_cc_interfaces->interface_tree;
1707  return new_cc_interfaces;
1708 }
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
char is_original_caller
Definition: ccss.c:1655
struct cc_monitor_tree * interface_tree
Definition: ccss.c:1659
#define ast_calloc(a, b)
Definition: astmm.h:82
unsigned int dial_parent_id
Definition: ccss.c:1632
static struct extension_monitor_pvt* extension_monitor_pvt_init ( void  )
static

Definition at line 1725 of file ccss.c.

References ast_calloc, AST_LIST_HEAD_INIT_NOLOCK, and extension_monitor_pvt::child_dialstrings.

Referenced by cc_extension_monitor_init().

1726 {
1727  struct extension_monitor_pvt *ext_pvt = ast_calloc(1, sizeof(*ext_pvt));
1728  if (!ext_pvt) {
1729  return NULL;
1730  }
1732  return ext_pvt;
1733 }
struct extension_monitor_pvt::@235 child_dialstrings
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:666
#define ast_calloc(a, b)
Definition: astmm.h:82
Private data for an extension monitor.
Definition: ccss.c:1547
static struct ast_cc_agent_callbacks* find_agent_callbacks ( struct ast_channel chan)
static

Definition at line 980 of file ccss.c.

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

Referenced by cc_agent_init().

981 {
982  struct cc_agent_backend *backend;
983  const struct ast_cc_agent_callbacks *callbacks = NULL;
984  struct ast_cc_config_params *cc_params;
985  char type[32];
986 
987  cc_params = ast_channel_get_cc_config_params(chan);
988  if (!cc_params) {
989  return NULL;
990  }
991  switch (ast_get_cc_agent_policy(cc_params)) {
993  ast_copy_string(type, "generic", sizeof(type));
994  break;
995  case AST_CC_AGENT_NATIVE:
996  ast_channel_get_cc_agent_type(chan, type, sizeof(type));
997  break;
998  default:
999  ast_log_dynamic_level(cc_logger_level, "Not returning agent callbacks since this channel is configured not to have a CC agent\n");
1000  return NULL;
1001  }
1002 
1004  AST_RWLIST_TRAVERSE(&cc_agent_backends, backend, next) {
1005  if (!strcmp(backend->callbacks->type, type)) {
1006  ast_log_dynamic_level(cc_logger_level, "Returning agent backend %s\n", backend->callbacks->type);
1007  callbacks = backend->callbacks;
1008  break;
1009  }
1010  }
1012  return callbacks;
1013 }
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
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:9754
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
int ast_channel_get_cc_agent_type(struct ast_channel *chan, char *agent_type, size_t size)
Find the appropriate CC agent type to use given a channel.
Definition: channel.c:9793
struct ast_cc_agent_callbacks * callbacks
Definition: ccss.c:945
const char * type
Type of agent the callbacks belong to.
Definition: ccss.h:877
static const char type[]
Definition: chan_nbs.c:57
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int cc_logger_level
Definition: ccss.c:124
enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config)
Get the cc_agent_policy.
Definition: ccss.c:746
static struct cc_core_instance* find_cc_core_instance ( const int  core_id)
static

Definition at line 421 of file ccss.c.

References ao2_t_find, cc_core_instance::core_id, and OBJ_POINTER.

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

422 {
423  struct cc_core_instance finder = {.core_id = core_id,};
424 
425  return ao2_t_find(cc_core_instances, &finder, OBJ_POINTER, "Finding a core_instance");
426 }
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
static struct generic_monitor_instance_list* find_generic_monitor_instance_list ( const char *const  device_name)
static

Definition at line 1108 of file ccss.c.

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

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

1109 {
1110  struct generic_monitor_instance_list finder = {0};
1111  char *uppertech = ast_strdupa(device_name);
1112  ast_tech_to_upper(uppertech);
1113  finder.device_name = uppertech;
1114 
1115  return ao2_t_find(generic_monitors, &finder, OBJ_POINTER, "Finding generic monitor instance list");
1116 }
#define ao2_t_find(arg1, arg2, arg3, arg4)
Definition: astobj2.h:963
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
struct ao2_container * generic_monitors
Definition: ccss.c:1044
char * ast_tech_to_upper(char *dev_str)
Convert the tech portion of a device string to upper case.
Definition: strings.h:939
const char * device_name
Definition: ccss.c:1054
static struct ast_cc_monitor_callbacks* find_monitor_callbacks ( const char *const  type)
static

Definition at line 911 of file ccss.c.

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

Referenced by call_destructor_with_no_monitor(), and cc_device_monitor_init().

912 {
913  struct cc_monitor_backend *backend;
914  const struct ast_cc_monitor_callbacks *callbacks = NULL;
915 
917  AST_RWLIST_TRAVERSE(&cc_monitor_backends, backend, next) {
918  if (!strcmp(backend->callbacks->type, type)) {
919  ast_log_dynamic_level(cc_logger_level, "Returning monitor backend %s\n", backend->callbacks->type);
920  callbacks = backend->callbacks;
921  break;
922  }
923  }
925  return callbacks;
926 }
const char * type
Type of monitor the callbacks belong to.
Definition: ccss.h:566
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.c:890
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
static const char type[]
Definition: chan_nbs.c:57
Callbacks defined by CC monitors.
Definition: ccss.h:559
static int cc_logger_level
Definition: ccss.c:124
static void generic_agent_devstate_cb ( const struct ast_event event,
void *  userdata 
)
static

Definition at line 2510 of file ccss.c.

References ast_cc_agent_caller_available(), ast_event_get_ie_uint(), AST_EVENT_IE_STATE, ast_taskprocessor_push(), cc_generic_is_device_available(), cc_ref(), cc_unref(), ast_cc_agent::core_id, ast_cc_agent::device_name, and generic_agent_devstate_unsubscribe().

Referenced by cc_generic_agent_start_monitoring().

2511 {
2512  struct ast_cc_agent *agent = userdata;
2513  enum ast_device_state new_state;
2514 
2515  new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
2516  if (!cc_generic_is_device_available(new_state)) {
2517  /* Not interested in this new state of the device. It is still busy. */
2518  return;
2519  }
2520 
2521  /* We can't unsubscribe from device state events here because it causes a deadlock */
2523  cc_ref(agent, "ref agent for device state unsubscription"))) {
2524  cc_unref(agent, "Unref agent unsubscribing from devstate failed");
2525  }
2526  ast_cc_agent_caller_available(agent->core_id, "%s is no longer busy", agent->device_name);
2527 }
ast_device_state
Device States.
Definition: devicestate.h:51
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static void * cc_ref(void *obj, const char *debug)
Definition: ccss.c:134
static int generic_agent_devstate_unsubscribe(void *data)
Definition: ccss.c:2498
int ast_cc_agent_caller_available(int core_id, const char *const debug,...)
Indicate that a previously unavailable caller has become available.
Definition: ccss.c:3554
unsigned int core_id
Definition: ccss.h:832
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
Definition: event.c:1075
char device_name[1]
Definition: ccss.h:858
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1024
Generic State IE Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: UINT The actual state values dep...
Definition: event_defs.h:115
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
static int generic_agent_devstate_unsubscribe ( void *  data)
static

Definition at line 2498 of file ccss.c.

References ast_event_unsubscribe(), cc_unref(), ast_cc_agent::private_data, and cc_generic_agent_pvt::sub.

Referenced by generic_agent_devstate_cb().

2499 {
2500  struct ast_cc_agent *agent = data;
2501  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2502 
2503  if (generic_pvt->sub != NULL) {
2504  generic_pvt->sub = ast_event_unsubscribe(generic_pvt->sub);
2505  }
2506  cc_unref(agent, "Done unsubscribing from devstate");
2507  return 0;
2508 }
void * private_data
Definition: ccss.h:854
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
struct ast_event_sub * sub
Definition: ccss.c:2365
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
Definition: event.c:987
static int generic_monitor_cmp_fn ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 1100 of file ccss.c.

References CMP_MATCH, CMP_STOP, and generic_monitor_instance_list::device_name.

Referenced by ast_cc_init().

1101 {
1102  const struct generic_monitor_instance_list *generic_list1 = obj;
1103  const struct generic_monitor_instance_list *generic_list2 = arg;
1104 
1105  return !strcmp(generic_list1->device_name, generic_list2->device_name) ? CMP_MATCH | CMP_STOP : 0;
1106 }
const char * device_name
Definition: ccss.c:1054
static void generic_monitor_devstate_cb ( const struct ast_event event,
void *  userdata 
)
static

Definition at line 1214 of file ccss.c.

References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_STATE, ast_free, ast_strdup, ast_taskprocessor_push(), generic_tp_cb_data::device_name, generic_monitor_devstate_tp_cb(), and generic_tp_cb_data::new_state.

Referenced by create_new_generic_list().

1215 {
1216  /* Wow, it's cool that we've picked up on a state change, but we really want
1217  * the actual work to be done in the core's taskprocessor execution thread
1218  * so that all monitor operations can be serialized. Locks?! We don't need
1219  * no steenkin' locks!
1220  */
1221  struct generic_tp_cb_data *gtcd = ast_calloc(1, sizeof(*gtcd));
1222 
1223  if (!gtcd) {
1224  return;
1225  }
1226 
1228  ast_free(gtcd);
1229  return;
1230  }
1232 
1234  ast_free((char *)gtcd->device_name);
1235  ast_free(gtcd);
1236  }
1237 }
#define ast_strdup(a)
Definition: astmm.h:109
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static int generic_monitor_devstate_tp_cb(void *data)
Definition: ccss.c:1166
const char * device_name
Definition: ccss.c:1162
#define ast_free(a)
Definition: astmm.h:97
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
Definition: event.c:1075
#define ast_calloc(a, b)
Definition: astmm.h:82
Generic State IE Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: UINT The actual state values dep...
Definition: event_defs.h:115
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
Definition: event.c:1102
Device Name Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: STR.
Definition: event_defs.h:107
enum ast_device_state new_state
Definition: ccss.c:1163
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
static int generic_monitor_devstate_tp_cb ( void *  data)
static

Definition at line 1166 of file ccss.c.

References ast_cc_monitor_callee_available(), AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_UNAVAILABLE, ast_free, AST_LIST_TRAVERSE, cc_generic_is_device_available(), cc_unref(), generic_monitor_instance::core_id, generic_monitor_instance_list::current_state, generic_tp_cb_data::device_name, find_generic_monitor_instance_list(), generic_monitor_instance_list::fit_for_recall, generic_monitor_instance::is_suspended, generic_monitor_instance_list::list, generic_monitor_instance::monitoring, and generic_tp_cb_data::new_state.

Referenced by generic_monitor_devstate_cb().

1167 {
1168  struct generic_tp_cb_data *gtcd = data;
1169  enum ast_device_state new_state = gtcd->new_state;
1170  enum ast_device_state previous_state = gtcd->new_state;
1171  const char *monitor_name = gtcd->device_name;
1172  struct generic_monitor_instance_list *generic_list;
1173  struct generic_monitor_instance *generic_instance;
1174 
1175  if (!(generic_list = find_generic_monitor_instance_list(monitor_name))) {
1176  /* The most likely cause for this is that we destroyed the monitor in the
1177  * time between subscribing to its device state and the time this executes.
1178  * Not really a big deal.
1179  */
1180  ast_free((char *) gtcd->device_name);
1181  ast_free(gtcd);
1182  return 0;
1183  }
1184 
1185  if (generic_list->current_state == new_state) {
1186  /* The device state hasn't actually changed, so we don't really care */
1187  cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1188  ast_free((char *) gtcd->device_name);
1189  ast_free(gtcd);
1190  return 0;
1191  }
1192 
1193  previous_state = generic_list->current_state;
1194  generic_list->current_state = new_state;
1195 
1196  if (cc_generic_is_device_available(new_state) &&
1197  (previous_state == AST_DEVICE_INUSE || previous_state == AST_DEVICE_UNAVAILABLE ||
1198  previous_state == AST_DEVICE_BUSY)) {
1199  AST_LIST_TRAVERSE(&generic_list->list, generic_instance, next) {
1200  if (!generic_instance->is_suspended && generic_instance->monitoring) {
1201  generic_instance->monitoring = 0;
1202  generic_list->fit_for_recall = 1;
1203  ast_cc_monitor_callee_available(generic_instance->core_id, "Generic monitored party has become available");
1204  break;
1205  }
1206  }
1207  }
1208  cc_unref(generic_list, "Kill reference of generic list in devstate taskprocessor callback");
1209  ast_free((char *) gtcd->device_name);
1210  ast_free(gtcd);
1211  return 0;
1212 }
ast_device_state
Device States.
Definition: devicestate.h:51
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
struct generic_monitor_instance_list::@233 list
const char * device_name
Definition: ccss.c:1162
static struct generic_monitor_instance_list * find_generic_monitor_instance_list(const char *const device_name)
Definition: ccss.c:1108
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:97
static int cc_generic_is_device_available(enum ast_device_state state)
Definition: ccss.c:1024
enum ast_device_state current_state
Definition: ccss.c:1055
enum ast_device_state new_state
Definition: ccss.c:1163
struct generic_monitor_instance * next
Definition: ccss.c:1050
int ast_cc_monitor_callee_available(const int core_id, const char *const debug,...)
Alert the core that a device being monitored has become available.
Definition: ccss.c:3532
static int generic_monitor_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 1094 of file ccss.c.

References ast_str_hash(), and generic_monitor_instance_list::device_name.

Referenced by ast_cc_init().

1095 {
1096  const struct generic_monitor_instance_list *generic_list = obj;
1097  return ast_str_hash(generic_list->device_name);
1098 }
const char * device_name
Definition: ccss.c:1054
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:949
static void generic_monitor_instance_list_destructor ( void *  obj)
static

Definition at line 1118 of file ccss.c.

References ast_event_unsubscribe(), ast_free, AST_LIST_REMOVE_HEAD, generic_monitor_instance_list::device_name, generic_monitor_instance_list::list, and generic_monitor_instance_list::sub.

Referenced by create_new_generic_list().

1119 {
1120  struct generic_monitor_instance_list *generic_list = obj;
1121  struct generic_monitor_instance *generic_instance;
1122 
1123  generic_list->sub = ast_event_unsubscribe(generic_list->sub);
1124  while ((generic_instance = AST_LIST_REMOVE_HEAD(&generic_list->list, next))) {
1125  ast_free(generic_instance);
1126  }
1127  ast_free((char *)generic_list->device_name);
1128 }
struct generic_monitor_instance_list::@233 list
struct ast_event_sub * sub
Definition: ccss.c:1072
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
const char * device_name
Definition: ccss.c:1054
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
Definition: event.c:987
struct generic_monitor_instance * next
Definition: ccss.c:1050
static void* generic_recall ( void *  data)
static

Definition at line 2548 of file ccss.c.

References ast_app_run_macro(), ast_cc_agent_recalling(), ast_cc_agent_set_interfaces_chanvar(), ast_cc_failed(), ast_copy_string(), AST_FORMAT_SLINEAR, ast_get_cc_callback_macro(), ast_get_cc_recall_timer(), ast_hangup(), ast_log_dynamic_level, ast_pbx_start(), ast_request_and_dial(), ast_setup_cc_recall_datastore(), ast_strlen_zero(), cc_generic_agent_pvt::cid_name, cc_generic_agent_pvt::cid_num, ast_channel::context, cc_generic_agent_pvt::context, ast_channel::exten, cc_generic_agent_pvt::exten, pbx_builtin_setvar_helper(), ast_channel::priority, ast_cc_agent::private_data, and S_OR.

Referenced by cc_generic_agent_recall().

2549 {
2550  struct ast_cc_agent *agent = data;
2551  struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
2552  const char *interface = S_OR(ast_get_cc_agent_dialstring(agent->cc_params), ast_strdupa(agent->device_name));
2553  const char *tech;
2554  char *target;
2555  int reason;
2556  struct ast_channel *chan;
2557  const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
2558  unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
2559 
2560  tech = interface;
2561  if ((target = strchr(interface, '/'))) {
2562  *target++ = '\0';
2563  }
2564  if (!(chan = ast_request_and_dial(tech, AST_FORMAT_SLINEAR, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
2565  /* Hmm, no channel. Sucks for you, bud.
2566  */
2567  ast_log_dynamic_level(cc_logger_level, "Core %u: Failed to call back %s for reason %d\n",
2568  agent->core_id, agent->device_name, reason);
2569  ast_cc_failed(agent->core_id, "Failed to call back device %s/%s", tech, target);
2570  return NULL;
2571  }
2572 
2573  /* We have a channel. It's time now to set up the datastore of recalled CC interfaces.
2574  * This will be a common task for all recall functions. If it were possible, I'd have
2575  * the core do it automatically, but alas I cannot. Instead, I will provide a public
2576  * function to do so.
2577  */
2578  ast_setup_cc_recall_datastore(chan, agent->core_id);
2580 
2581  ast_copy_string(chan->exten, generic_pvt->exten, sizeof(chan->exten));
2582  ast_copy_string(chan->context, generic_pvt->context, sizeof(chan->context));
2583  chan->priority = 1;
2584 
2585  pbx_builtin_setvar_helper(chan, "CC_EXTEN", generic_pvt->exten);
2586  pbx_builtin_setvar_helper(chan, "CC_CONTEXT", generic_pvt->context);
2587 
2588  if (!ast_strlen_zero(callback_macro)) {
2589  ast_log_dynamic_level(cc_logger_level, "Core %u: There's a callback macro configured for agent %s\n",
2590  agent->core_id, agent->device_name);
2591  if (ast_app_run_macro(NULL, chan, callback_macro, NULL)) {
2592  ast_cc_failed(agent->core_id, "Callback macro to %s failed. Maybe a hangup?", agent->device_name);
2593  ast_hangup(chan);
2594  return NULL;
2595  }
2596  }
2597  if (ast_pbx_start(chan)) {
2598  ast_cc_failed(agent->core_id, "PBX failed to start for %s.", agent->device_name);
2599  ast_hangup(chan);
2600  return NULL;
2601  }
2602  ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling",
2603  agent->device_name);
2604  return NULL;
2605 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
Main Channel structure associated with a channel.
Definition: channel.h:742
int priority
Definition: channel.h:841
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3613
void * private_data
Definition: ccss.h:854
char cid_num[AST_CHANNEL_NAME]
Definition: ccss.c:2379
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
struct ast_cc_config_params * cc_params
Definition: ccss.h:842
unsigned int ast_get_cc_recall_timer(struct ast_cc_config_params *config)
Get the cc_recall_timer.
Definition: ccss.c:810
char context[AST_CHANNEL_NAME]
Definition: ccss.c:2403
char exten[AST_CHANNEL_NAME]
Definition: ccss.c:2395
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
int ast_cc_agent_recalling(int core_id, const char *const debug,...)
Tell the CC core that a caller is currently recalling.
Definition: ccss.c:3565
int ast_cc_agent_set_interfaces_chanvar(struct ast_channel *chan)
Set the first level CC_INTERFACES channel variable for a channel.
Definition: ccss.c:3365
int ast_setup_cc_recall_datastore(struct ast_channel *chan, const int core_id)
Set up a CC recall datastore on a channel.
Definition: ccss.c:3139
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const char * ast_get_cc_agent_dialstring(struct ast_cc_config_params *config)
Get the cc_agent_dialstring.
Definition: ccss.c:840
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
const char * ast_get_cc_callback_macro(struct ast_cc_config_params *config)
Get the name of the callback_macro.
Definition: ccss.c:874
int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char *macro_name, const char *macro_args)
Run a macro on a channel, placing an optional second channel into autoservice.
Definition: app.c:294
unsigned int core_id
Definition: ccss.h:832
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...
Definition: pbx.c:10546
char device_name[1]
Definition: ccss.h:858
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
struct ast_channel * ast_request_and_dial(const char *type, format_t format, const struct ast_channel *requestor, void *data, int timeout, int *reason, const char *cid_num, const char *cid_name)
Request a channel of a given type, with data as optional information used by the low level module and...
Definition: channel.c:5650
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
char cid_name[AST_CHANNEL_NAME]
Definition: ccss.c:2387
static int cc_logger_level
Definition: ccss.c:124
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static char* handle_cc_kill ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4262 of file ccss.c.

References ao2_t_callback, ast_cli_args::argc, ast_cli_args::argv, ast_cli_complete(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_id(), cc_core_instance::core_id, errno, kill_cores(), ast_cli_args::line, ast_cli_args::n, OBJ_NODATA, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

4263 {
4264  static const char * const option[] = { "core", "all", NULL };
4265 
4266  switch (cmd) {
4267  case CLI_INIT:
4268  e->command = "cc cancel";
4269  e->usage =
4270  "Usage: cc cancel can be used in two ways.\n"
4271  " 1. 'cc cancel core [core ID]' will cancel the CC transaction with\n"
4272  " core ID equal to the specified core ID.\n"
4273  " 2. 'cc cancel all' will cancel all active CC transactions.\n";
4274  return NULL;
4275  case CLI_GENERATE:
4276  if (a->pos == 2) {
4277  return ast_cli_complete(a->word, option, a->n);
4278  }
4279  if (a->pos == 3) {
4280  return complete_core_id(a->line, a->word, a->pos, a->n);
4281  }
4282  return NULL;
4283  }
4284 
4285  if (a->argc == 4) {
4286  int core_id;
4287  char *endptr;
4288  if (strcasecmp(a->argv[2], "core")) {
4289  return CLI_SHOWUSAGE;
4290  }
4291  core_id = strtol(a->argv[3], &endptr, 10);
4292  if ((errno != 0 && core_id == 0) || (endptr == a->argv[3])) {
4293  return CLI_SHOWUSAGE;
4294  }
4295  ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, &core_id, "CLI Killing Core Id");
4296  } else if (a->argc == 3) {
4297  if (strcasecmp(a->argv[2], "all")) {
4298  return CLI_SHOWUSAGE;
4299  }
4300  ao2_t_callback(cc_core_instances, OBJ_NODATA, kill_cores, NULL, "CLI Killing all CC cores");
4301  } else {
4302  return CLI_SHOWUSAGE;
4303  }
4304 
4305  return CLI_SUCCESS;
4306 }
const int argc
Definition: cli.h:154
Definition: cli.h:146
static char * complete_core_id(const char *line, const char *word, int pos, int state)
Definition: ccss.c:4239
const char * line
Definition: cli.h:156
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: cli.c:1535
const int n
Definition: cli.h:159
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
static int kill_cores(void *obj, void *arg, int flags)
Definition: ccss.c:4228
#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:909
int errno
char * command
Definition: cli.h:180
const char * word
Definition: cli.h:157
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
static char* handle_cc_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4195 of file ccss.c.

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

4196 {
4197  int *cli_fd;
4198 
4199  switch (cmd) {
4200  case CLI_INIT:
4201  e->command = "cc report status";
4202  e->usage =
4203  "Usage: cc report status\n"
4204  " Report the current status of any ongoing CC transactions\n";
4205  return NULL;
4206  case CLI_GENERATE:
4207  return NULL;
4208  }
4209 
4210  if (a->argc != 3) {
4211  return CLI_SHOWUSAGE;
4212  }
4213 
4214  cli_fd = ast_malloc(sizeof(*cli_fd));
4215  if (!cli_fd) {
4216  return CLI_FAILURE;
4217  }
4218 
4219  *cli_fd = a->fd;
4220 
4222  ast_free(cli_fd);
4223  return CLI_FAILURE;
4224  }
4225  return CLI_SUCCESS;
4226 }
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
const int argc
Definition: cli.h:154
Definition: cli.h:146
const int fd
Definition: cli.h:153
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define CLI_FAILURE
Definition: cli.h:45
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static int cc_cli_output_status(void *data)
Definition: ccss.c:4178
#define ast_malloc(a)
Definition: astmm.h:91
static struct ast_taskprocessor * cc_core_taskprocessor
Definition: ccss.c:116
static int has_device_monitors ( struct cc_core_instance core_instance)
static

check if the core instance has any device monitors

In any case where we end up removing a device monitor from the list of device monitors, it is important to see what the state of the list is afterwards. If we find that we only have extension monitors left, then no devices are actually being monitored. In such a case, we need to declare that CC has failed for this call. This function helps those cases to determine if they should declare failure.

Parameters
core_instanceThe core instance we are checking for the existence of device monitors
Return values
0No device monitors exist on this core_instance
1There is still at least 1 device monitor remaining

Definition at line 2809 of file ccss.c.

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

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

2810 {
2811  struct ast_cc_monitor *iter;
2812  int res = 0;
2813 
2814  AST_LIST_TRAVERSE(core_instance->monitors, iter, next) {
2816  res = 1;
2817  break;
2818  }
2819  }
2820 
2821  return res;
2822 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
struct ast_cc_monitor * next
Definition: ccss.h:545
#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:497
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
static void initialize_cc_max_requests ( void  )
static

Definition at line 4114 of file ccss.c.

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

Referenced by ast_cc_init().

4115 {
4116  struct ast_config *cc_config;
4117  const char *cc_max_requests_str;
4118  struct ast_flags config_flags = {0,};
4119  char *endptr;
4120 
4121  cc_config = ast_config_load2("ccss.conf", "ccss", config_flags);
4122  if (!cc_config || cc_config == CONFIG_STATUS_FILEINVALID) {
4123  ast_log(LOG_WARNING, "Could not find valid ccss.conf file. Using cc_max_requests default\n");
4125  return;
4126  }
4127 
4128  if (!(cc_max_requests_str = ast_variable_retrieve(cc_config, "general", "cc_max_requests"))) {
4129  ast_config_destroy(cc_config);
4131  return;
4132  }
4133 
4134  global_cc_max_requests = strtol(cc_max_requests_str, &endptr, 10);
4135 
4136  if (!ast_strlen_zero(endptr)) {
4137  ast_log(LOG_WARNING, "Invalid input given for cc_max_requests. Using default\n");
4139  }
4140 
4141  ast_config_destroy(cc_config);
4142  return;
4143 }
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
static unsigned int global_cc_max_requests
Definition: ccss.c:128
#define LOG_WARNING
Definition: logger.h:144
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: config.c:2499
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define GLOBAL_CC_MAX_REQUESTS_DEFAULT
Definition: ccss.c:543
static int is_state_change_valid ( enum cc_state  current_state,
const enum cc_state  new_state,
struct ast_cc_agent agent 
)
static

Definition at line 2713 of file ccss.c.

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

Referenced by cc_do_state_change().

2714 {
2715  int is_valid = 0;
2716  switch (new_state) {
2717  case CC_AVAILABLE:
2718  ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to state %u? That should never happen.\n",
2719  agent->core_id, new_state);
2720  break;
2721  case CC_CALLER_OFFERED:
2722  if (current_state == CC_AVAILABLE) {
2723  is_valid = 1;
2724  }
2725  break;
2726  case CC_CALLER_REQUESTED:
2727  if (current_state == CC_CALLER_OFFERED ||
2728  (current_state == CC_AVAILABLE && ast_test_flag(agent, AST_CC_AGENT_SKIP_OFFER))) {
2729  is_valid = 1;
2730  }
2731  break;
2732  case CC_ACTIVE:
2733  if (current_state == CC_CALLER_REQUESTED || current_state == CC_CALLER_BUSY) {
2734  is_valid = 1;
2735  }
2736  break;
2737  case CC_CALLEE_READY:
2738  if (current_state == CC_ACTIVE) {
2739  is_valid = 1;
2740  }
2741  break;
2742  case CC_CALLER_BUSY:
2743  if (current_state == CC_CALLEE_READY) {
2744  is_valid = 1;
2745  }
2746  break;
2747  case CC_RECALLING:
2748  if (current_state == CC_CALLEE_READY) {
2749  is_valid = 1;
2750  }
2751  break;
2752  case CC_COMPLETE:
2753  if (current_state == CC_RECALLING) {
2754  is_valid = 1;
2755  }
2756  break;
2757  case CC_FAILED:
2758  is_valid = 1;
2759  break;
2760  default:
2761  ast_log_dynamic_level(cc_logger_level, "Core %u: Asked to change to unknown state %u\n",
2762  agent->core_id, new_state);
2763  break;
2764  }
2765 
2766  return is_valid;
2767 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
unsigned int core_id
Definition: ccss.h:832
static int cc_logger_level
Definition: ccss.c:124
static int kill_cores ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 4228 of file ccss.c.

References ast_cc_failed(), and cc_core_instance::core_id.

Referenced by handle_cc_kill().

4229 {
4230  int *core_id = arg;
4231  struct cc_core_instance *core_instance = obj;
4232 
4233  if (!core_id || (core_instance->core_id == *core_id)) {
4234  ast_cc_failed(core_instance->core_id, "CC transaction canceled administratively\n");
4235  }
4236  return 0;
4237 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3613
static void kill_duplicate_offers ( char *  caller)
static

Definition at line 2252 of file ccss.c.

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

Referenced by cc_core_init_instance().

2253 {
2254  unsigned long match_flags = MATCH_NO_REQUEST;
2255  struct ao2_iterator *dups_iter;
2256 
2257  /*
2258  * Must remove the ref that was in cc_core_instances outside of
2259  * the container lock to prevent deadlock.
2260  */
2262  match_agent, caller, &match_flags, "Killing duplicate offers");
2263  if (dups_iter) {
2264  /* Now actually unref any duplicate offers by simply destroying the iterator. */
2265  ao2_iterator_destroy(dups_iter);
2266  }
2267 }
#define ao2_t_callback_data(arg1, arg2, arg3, arg4, arg5, arg6)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container...
Definition: astobj2.h:942
match_flags
Definition: ccss.c:459
static int match_agent(void *obj, void *arg, void *data, int flags)
Definition: ccss.c:482
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
static struct ao2_container * cc_core_instances
Definition: ccss.c:317
static int match_agent ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 482 of file ccss.c.

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

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

483 {
484  struct cc_core_instance *core_instance = obj;
485  const char *name = arg;
486  unsigned long match_flags = *(unsigned long *)data;
487  int possible_match = 0;
488 
489  if ((match_flags & MATCH_NO_REQUEST) && core_instance->current_state < CC_CALLER_REQUESTED) {
490  possible_match = 1;
491  }
492 
493  if ((match_flags & MATCH_REQUEST) && core_instance->current_state >= CC_CALLER_REQUESTED) {
494  possible_match = 1;
495  }
496 
497  if (!possible_match) {
498  return 0;
499  }
500 
501  if (!strcmp(core_instance->agent->device_name, name)) {
502  return CMP_MATCH | CMP_STOP;
503  }
504  return 0;
505 }
enum cc_state current_state
Definition: ccss.c:327
static const char name[]
match_flags
Definition: ccss.c:459
char device_name[1]
Definition: ccss.h:858
struct ast_cc_agent * agent
Definition: ccss.c:331
static const char* monitor_policy_to_str ( enum ast_cc_monitor_policies  policy)
static

Definition at line 629 of file ccss.c.

References AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, and AST_CC_MONITOR_NEVER.

Referenced by ast_cc_get_param().

630 {
631  switch (policy) {
633  return "never";
635  return "native";
637  return "generic";
639  return "always";
640  default:
641  /* This should never happen... */
642  return "";
643  }
644 }
static int offer_timer_expire ( const void *  data)
static

Definition at line 2428 of file ccss.c.

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

Referenced by cc_generic_agent_start_offer_timer().

2429 {
2430  struct ast_cc_agent *agent = (struct ast_cc_agent *) data;
2431  struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
2432  ast_log_dynamic_level(cc_logger_level, "Core %u: Queuing change request because offer timer has expired.\n",
2433  agent->core_id);
2434  agent_pvt->offer_timer_id = -1;
2435  ast_cc_failed(agent->core_id, "Generic agent %s offer timer expired", agent->device_name);
2436  cc_unref(agent, "Remove scheduler's reference to the agent");
2437  return 0;
2438 }
int ast_cc_failed(int core_id, const char *const debug,...)
Indicate failure has occurred.
Definition: ccss.c:3613
void * private_data
Definition: ccss.h:854
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
Structure representing an agent.
Definition: chan_agent.c:252
unsigned int core_id
Definition: ccss.h:832
char device_name[1]
Definition: ccss.h:858
static int cc_logger_level
Definition: ccss.c:124
static int print_stats_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 4165 of file ccss.c.

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

Referenced by cc_cli_output_status().

4166 {
4167  int *cli_fd = arg;
4168  struct cc_core_instance *core_instance = obj;
4169 
4170  ast_cli(*cli_fd, "%d\t\t%s\t\t%s\n", core_instance->core_id, core_instance->agent->device_name,
4171  cc_state_to_string(core_instance->current_state));
4172  AST_LIST_LOCK(core_instance->monitors);
4173  cc_cli_print_monitor_stats(AST_LIST_FIRST(core_instance->monitors), *cli_fd, 0);
4174  AST_LIST_UNLOCK(core_instance->monitors);
4175  return 0;
4176 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
static const char * cc_state_to_string(enum cc_state state)
Definition: ccss.c:397
enum cc_state current_state
Definition: ccss.c:327
static void cc_cli_print_monitor_stats(struct ast_cc_monitor *monitor, int fd, int parent_id)
Definition: ccss.c:4145
char device_name[1]
Definition: ccss.h:858
struct ast_cc_agent * agent
Definition: ccss.c:331
static void request_cc ( struct cc_core_instance core_instance)
static

Definition at line 2824 of file ccss.c.

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

Referenced by cc_caller_requested().

2825 {
2826  struct ast_cc_monitor *monitor_iter;
2827  AST_LIST_LOCK(core_instance->monitors);
2828  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
2829  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
2830  if (monitor_iter->callbacks->request_cc(monitor_iter, &monitor_iter->available_timer_id)) {
2832  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
2833  monitor_iter->interface->device_name, 1);
2834  cc_unref(monitor_iter, "request_cc failed. Unref list's reference to monitor");
2835  } else {
2836  manager_event(EVENT_FLAG_CC, "CCRequested",
2837  "CoreID: %d\r\n"
2838  "Caller: %s\r\n"
2839  "Callee: %s\r\n",
2840  core_instance->core_id, core_instance->agent->device_name, monitor_iter->interface->device_name);
2841  }
2842  }
2843  }
2845 
2846  if (!has_device_monitors(core_instance)) {
2847  ast_cc_failed(core_instance->core_id, "All device monitors failed to request CC");
2848  }
2849  AST_LIST_UNLOCK(core_instance->monitors);
2850 }
int(* request_cc)(struct ast_cc_monitor *monitor, int *available_timer_id)
Request CCSS.
Definition: ccss.h:582
struct cc_monitor_tree * monitors
Definition: ccss.c:335
struct ast_cc_monitor * next
Definition: ccss.h:545
#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:3613
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void cc_extension_monitor_change_is_valid(struct cc_core_instance *core_instance, unsigned int parent_id, const char *const device_name, int is_valid)
Definition: ccss.c:1780
#define EVENT_FLAG_CC
Definition: manager.h:86
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
unsigned int parent_id
Definition: ccss.h:507
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
struct ast_cc_interface * interface
Definition: ccss.h:497
char device_name[1]
Definition: ccss.h:858
int available_timer_id
Definition: ccss.h:530
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:2809
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
struct ast_cc_agent * agent
Definition: ccss.c:331
char device_name[1]
Definition: ccss.h:822
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:534
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
static enum ast_cc_agent_policies str_to_agent_policy ( const char *const  value)
static

Definition at line 584 of file ccss.c.

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

Referenced by ast_cc_set_param().

585 {
586  if (!strcasecmp(value, "never")) {
587  return AST_CC_AGENT_NEVER;
588  } else if (!strcasecmp(value, "native")) {
589  return AST_CC_AGENT_NATIVE;
590  } else if (!strcasecmp(value, "generic")) {
591  return AST_CC_AGENT_GENERIC;
592  } else {
593  ast_log(LOG_WARNING, "%s is an invalid value for cc_agent_policy. Switching to 'never'\n", value);
594  return AST_CC_AGENT_NEVER;
595  }
596 }
#define LOG_WARNING
Definition: logger.h:144
int value
Definition: syslog.c:39
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static enum ast_cc_monitor_policies str_to_monitor_policy ( const char *const  value)
static

Definition at line 598 of file ccss.c.

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

Referenced by ast_cc_set_param().

599 {
600  if (!strcasecmp(value, "never")) {
601  return AST_CC_MONITOR_NEVER;
602  } else if (!strcasecmp(value, "native")) {
603  return AST_CC_MONITOR_NATIVE;
604  } else if (!strcasecmp(value, "generic")) {
605  return AST_CC_MONITOR_GENERIC;
606  } else if (!strcasecmp(value, "always")) {
607  return AST_CC_MONITOR_ALWAYS;
608  } else {
609  ast_log(LOG_WARNING, "%s is an invalid value for cc_monitor_policy. Switching to 'never'\n", value);
610  return AST_CC_MONITOR_NEVER;
611  }
612 }
#define LOG_WARNING
Definition: logger.h:144
int value
Definition: syslog.c:39
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static void suspend ( struct cc_core_instance core_instance)
static

Definition at line 2919 of file ccss.c.

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

Referenced by cc_caller_busy(), and handle_controlstreamfile().

2920 {
2921  struct ast_cc_monitor *monitor_iter;
2922  AST_LIST_LOCK(core_instance->monitors);
2923  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
2924  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
2925  if (monitor_iter->callbacks->suspend(monitor_iter)) {
2927  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
2928  monitor_iter->interface->device_name, 1);
2929  cc_unref(monitor_iter, "suspend failed. Unref list's reference to monitor");
2930  }
2931  }
2932  }
2934 
2935  if (!has_device_monitors(core_instance)) {
2936  ast_cc_failed(core_instance->core_id, "All device monitors failed to suspend CC");
2937  }
2938  AST_LIST_UNLOCK(core_instance->monitors);
2939 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
struct ast_cc_monitor * next
Definition: ccss.h:545
#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:3613
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void cc_extension_monitor_change_is_valid(struct cc_core_instance *core_instance, unsigned int parent_id, const char *const device_name, int is_valid)
Definition: ccss.c:1780
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
unsigned int parent_id
Definition: ccss.h:507
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
int(* suspend)(struct ast_cc_monitor *monitor)
Suspend monitoring.
Definition: ccss.h:595
struct ast_cc_interface * interface
Definition: ccss.h:497
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:2809
#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:822
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:534
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804
static void unsuspend ( struct cc_core_instance core_instance)
static

Definition at line 2866 of file ccss.c.

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

Referenced by cc_active().

2867 {
2868  struct ast_cc_monitor *monitor_iter;
2869  AST_LIST_LOCK(core_instance->monitors);
2870  AST_LIST_TRAVERSE_SAFE_BEGIN(core_instance->monitors, monitor_iter, next) {
2871  if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
2872  if (monitor_iter->callbacks->unsuspend(monitor_iter)) {
2874  cc_extension_monitor_change_is_valid(core_instance, monitor_iter->parent_id,
2875  monitor_iter->interface->device_name, 1);
2876  cc_unref(monitor_iter, "unsuspend failed. Unref list's reference to monitor");
2877  }
2878  }
2879  }
2881 
2882  if (!has_device_monitors(core_instance)) {
2883  ast_cc_failed(core_instance->core_id, "All device monitors failed to unsuspend CC");
2884  }
2885  AST_LIST_UNLOCK(core_instance->monitors);
2886 }
struct cc_monitor_tree * monitors
Definition: ccss.c:335
struct ast_cc_monitor * next
Definition: ccss.h:545
#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:3613
static void * cc_unref(void *obj, const char *debug)
Definition: ccss.c:140
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void cc_extension_monitor_change_is_valid(struct cc_core_instance *core_instance, unsigned int parent_id, const char *const device_name, int is_valid)
Definition: ccss.c:1780
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
unsigned int parent_id
Definition: ccss.h:507
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
struct ast_cc_interface * interface
Definition: ccss.h:497
int(* unsuspend)(struct ast_cc_monitor *monitor)
Unsuspend monitoring.
Definition: ccss.h:623
static int has_device_monitors(struct cc_core_instance *core_instance)
check if the core instance has any device monitors
Definition: ccss.c:2809
#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:822
struct ast_cc_monitor_callbacks * callbacks
Definition: ccss.h:534
enum ast_cc_monitor_class monitor_class
Definition: ccss.h:804

Variable Documentation

struct cc_agent_backends cc_agent_backends = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
struct ast_cli_entry cc_cli[]
static
Initial value:
= {
AST_CLI_DEFINE(handle_cc_status, "Reports CC stats"),
AST_CLI_DEFINE(handle_cc_kill, "Kill a CC transaction"),
}
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
static char * handle_cc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: ccss.c:4195
static char * handle_cc_kill(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: ccss.c:4262

Definition at line 4308 of file ccss.c.

struct ao2_container* cc_core_instances
static

Definition at line 317 of file ccss.c.

const int CC_CORE_INSTANCES_BUCKETS = 17
static

Definition at line 316 of file ccss.c.

struct ast_taskprocessor* cc_core_taskprocessor
static

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

Definition at line 116 of file ccss.c.

struct ast_cc_config_params cc_default_params
static

Definition at line 545 of file ccss.c.

Referenced by ast_cc_default_config_params().

int cc_logger_level
static

Logger level registered by the CC core.

Definition at line 124 of file ccss.c.

const char* CC_LOGGER_LEVEL_NAME = "CC"
static

Name printed on all CC log messages.

Definition at line 120 of file ccss.c.

struct cc_monitor_backends cc_monitor_backends = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
int cc_request_count
static

The current number of CC requests in the system

Definition at line 132 of file ccss.c.

struct ast_sched_thread* cc_sched_thread
static

The sched_thread ID used for all generic CC timeouts

Definition at line 106 of file ccss.c.

struct { ... } cc_service_to_string_map[]

Referenced by cc_service_to_string().

struct { ... } cc_state_to_string_map[]

Referenced by cc_state_to_string().

const char* cccancel_app = "CallCompletionCancel"
static

Definition at line 4043 of file ccss.c.

const char* ccreq_app = "CallCompletionRequest"
static

Definition at line 3992 of file ccss.c.

int core_id_counter
static

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

Definition at line 111 of file ccss.c.

int dialed_cc_interface_counter
static

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

Definition at line 1605 of file ccss.c.

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

Definition at line 1719 of file ccss.c.

struct ast_cc_agent_callbacks generic_agent_callbacks
static

Definition at line 2343 of file ccss.c.

struct ast_cc_monitor_callbacks generic_monitor_cbs
static

Definition at line 1035 of file ccss.c.

Referenced by ast_cc_init(), and cc_shutdown().

unsigned int global_cc_max_requests
static

Parsed configuration value for cc_max_requests

Definition at line 128 of file ccss.c.

Referenced by ast_cc_request_is_within_limits().

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

Definition at line 3133 of file ccss.c.

enum ast_cc_service_type service

Definition at line 373 of file ccss.c.

const char* service_string

Definition at line 374 of file ccss.c.

Definition at line 383 of file ccss.c.

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

Definition at line 3012 of file ccss.c.

Referenced by cc_do_state_change().

const char* state_string

Definition at line 384 of file ccss.c.