diff options
Diffstat (limited to 'include/asterisk/ccss.h')
-rw-r--r-- | include/asterisk/ccss.h | 1582 |
1 files changed, 1582 insertions, 0 deletions
diff --git a/include/asterisk/ccss.h b/include/asterisk/ccss.h new file mode 100644 index 000000000..c2d7ec850 --- /dev/null +++ b/include/asterisk/ccss.h @@ -0,0 +1,1582 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2010, Digium, Inc. + * + * Mark Michelson <mmichelson@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * \brief Call Completion Supplementary Services API + * \author Mark Michelson <mmichelson@digium.com> + */ + +#ifndef _ASTERISK_CCSS_H +#define _ASTERISK_CCSS_H + +#include "asterisk.h" + +#include "asterisk/linkedlists.h" +#include "asterisk/devicestate.h" + +enum ast_cc_service_type { + /* No Service available/requested */ + AST_CC_NONE, + /* Call Completion Busy Subscriber */ + AST_CC_CCBS, + /* Call Completion No Response */ + AST_CC_CCNR, + /* Call Completion Not Logged In (currently SIP only) */ + AST_CC_CCNL, +}; + +/*! + * \since 1.8 + * \brief The various possibilities for cc_agent_policy values + */ +enum ast_cc_agent_policies { + /*! Never offer CCSS to the caller */ + AST_CC_AGENT_NEVER, + /*! Offer CCSS using native signaling */ + AST_CC_AGENT_NATIVE, + /*! Use generic agent for caller */ + AST_CC_AGENT_GENERIC, +}; + +/*! + * \brief agent flags that can alter core behavior + */ +enum ast_cc_agent_flags { + /* Some agent types allow for a caller to + * request CC without reaching the CC_CALLER_OFFERED + * state. In other words, the caller can request + * CC while he is still on the phone from the failed + * call. The generic agent is an agent which allows + * for this behavior. + */ + AST_CC_AGENT_SKIP_OFFER = (1 << 0), +}; + +/*! + * \since 1.8 + * \brief The various possibilities for cc_monitor_policy values + */ +enum ast_cc_monitor_policies { + /*! Never accept CCSS offers from callee */ + AST_CC_MONITOR_NEVER, + /* CCSS only available if callee offers it through signaling */ + AST_CC_MONITOR_NATIVE, + /*! Always use CCSS generic monitor for callee + * Note that if callee offers CCSS natively, we still + * will use a generic CCSS monitor if this is set + */ + AST_CC_MONITOR_GENERIC, + /*! Accept native CCSS offers, but if no offer is present, + * use a generic CCSS monitor + */ + AST_CC_MONITOR_ALWAYS, +}; + +/* Forward declaration. Struct is in main/ccss.c */ +struct ast_cc_config_params; + +/*! + * \since 1.8 + * \brief Queue an AST_CONTROL_CC frame + * + * \note + * Since this function calls ast_queue_frame, the channel will be + * locked during the course of this function. + * + * \param chan The channel onto which to queue the frame + * \param monitor_type The type of monitor to use when CC is requested + * \param dialstring The dial string used to call the device + * \param service The type of CC service the device is willing to offer + * \param private_data If 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. + * \retval 0 Success + * \retval -1 Error + */ +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); + +/*! + * \brief Allocate and initialize an ast_cc_config_params structure + * + * \note + * Reasonable default values are chosen for the parameters upon allocation. + * + * \retval NULL Unable to allocate the structure + * \retval non-NULL A pointer to the newly allocated and initialized structure + */ +struct ast_cc_config_params *__ast_cc_config_params_init(const char *file, int line, const char *function); + +/*! + * \brief Allocate and initialize an ast_cc_config_params structure + * + * \note + * Reasonable default values are chosen for the parameters upon allocation. + * + * \retval NULL Unable to allocate the structure + * \retval non-NULL A pointer to the newly allocated and initialized structure + */ +#define ast_cc_config_params_init() __ast_cc_config_params_init(__FILE__, __LINE__, __PRETTY_FUNCTION__) + +/*! + * \brief Free memory from CCSS configuration params + * + * \note + * Just a call to ast_free for now... + * + * \param params Pointer to structure whose memory we need to free + * \retval void + */ +void ast_cc_config_params_destroy(struct ast_cc_config_params *params); + +/*! + * \brief 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. + * + * \param params The parameter structure to set the value on + * \param name The name of the cc parameter + * \param value The value of the parameter + * \retval 0 Success + * \retval -1 Failure + */ +int ast_cc_set_param(struct ast_cc_config_params *params, const char * const name, + const char * value); + +/*! + * \brief get a CCSS configuration parameter, given its name + * + * \note + * Useful when reading input as a string, like from dialplan or + * manager. + * + * \param params The CCSS configuration from which to get the value + * \param name The name of the CCSS parameter we want + * \param buf A preallocated buffer to hold the value + * \param buf_len The size of buf + * \retval 0 Success + * \retval -1 Failure + */ +int ast_cc_get_param(struct ast_cc_config_params *params, const char * const name, + char *buf, size_t buf_len); + +/*! + * \since 1.8 + * \brief Is this a CCSS configuration parameter? + * \param name Name of configuration option being parsed. + * \retval 1 Yes, this is a CCSS configuration parameter. + * \retval 0 No, this is not a CCSS configuration parameter. + */ +int ast_cc_is_config_param(const char * const name); + +/*! + * \since 1.8 + * \brief copy CCSS configuration parameters from one structure to another + * + * \details + * 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. + * + * \param src The structure from which data is copied + * \param dest The structure to which data is copied + * \retval -1 Copy failed (no way for this to happen yet) + * \retval 0 Copy succeeded + */ +void ast_cc_copy_config_params(struct ast_cc_config_params *dest, const struct ast_cc_config_params *src); + +/*! + * \since 1.8 + * \brief Get the cc_agent_policy + * \param config The configuration to retrieve the policy from + * \return The current cc_agent_policy for this configuration + */ +enum ast_cc_agent_policies ast_get_cc_agent_policy(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the cc_agent_policy + * \param config The configuration to set the cc_agent_policy on + * \param value The new cc_agent_policy we want to change to + * \retval 0 Success + * \retval -1 Failure (likely due to bad input) + */ +int ast_set_cc_agent_policy(struct ast_cc_config_params *config, enum ast_cc_agent_policies value); + +/*! + * \since 1.8 + * \brief Get the cc_monitor_policy + * \param config The configuration to retrieve the cc_monitor_policy from + * \return The cc_monitor_policy retrieved from the configuration + */ +enum ast_cc_monitor_policies ast_get_cc_monitor_policy(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the cc_monitor_policy + * \param config The configuration to set the cc_monitor_policy on + * \param value The new cc_monitor_policy we want to change to + * \retval 0 Success + * \retval -1 Failure (likely due to bad input) + */ +int ast_set_cc_monitor_policy(struct ast_cc_config_params *config, enum ast_cc_monitor_policies value); + +/*! + * \since 1.8 + * \brief Get the cc_offer_timer + * \param config The configuration to retrieve the cc_offer_timer from + * \return The cc_offer_timer from this configuration + */ +unsigned int ast_get_cc_offer_timer(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the cc_offer_timer + * \param config The configuration to set the cc_offer_timer on + * \param value The new cc_offer_timer we want to change to + * \retval void + */ +void ast_set_cc_offer_timer(struct ast_cc_config_params *config, unsigned int value); + +/*! + * \since 1.8 + * \brief Get the ccnr_available_timer + * \param config The configuration to retrieve the ccnr_available_timer from + * \return The ccnr_available_timer from this configuration + */ +unsigned int ast_get_ccnr_available_timer(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the ccnr_available_timer + * \param config The configuration to set the ccnr_available_timer on + * \param value The new ccnr_available_timer we want to change to + * \retval void + */ +void ast_set_ccnr_available_timer(struct ast_cc_config_params *config, unsigned int value); + +/*! + * \since 1.8 + * \brief Get the cc_recall_timer + * \param config The configuration to retrieve the cc_recall_timer from + * \return The cc_recall_timer from this configuration + */ +unsigned int ast_get_cc_recall_timer(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the cc_recall_timer + * \param config The configuration to set the cc_recall_timer on + * \param value The new cc_recall_timer we want to change to + * \retval void + */ +void ast_set_cc_recall_timer(struct ast_cc_config_params *config, unsigned int value); + +/*! + * \since 1.8 + * \brief Get the ccbs_available_timer + * \param config The configuration to retrieve the ccbs_available_timer from + * \return The ccbs_available_timer from this configuration + */ +unsigned int ast_get_ccbs_available_timer(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the ccbs_available_timer + * \param config The configuration to set the ccbs_available_timer on + * \param value The new ccbs_available_timer we want to change to + * \retval void + */ +void ast_set_ccbs_available_timer(struct ast_cc_config_params *config, unsigned int value); + +/*! + * \since 1.8 + * \brief Get the cc_agent_dialstring + * \param config The configuration to retrieve the cc_agent_dialstring from + * \return The cc_agent_dialstring from this configuration + */ +const char *ast_get_cc_agent_dialstring(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the cc_agent_dialstring + * \param config The configuration to set the cc_agent_dialstring on + * \param value The new cc_agent_dialstring we want to change to + * \retval void + */ +void ast_set_cc_agent_dialstring(struct ast_cc_config_params *config, const char *const value); + +/*! + * \since 1.8 + * \brief Get the cc_max_agents + * \param config The configuration to retrieve the cc_max_agents from + * \return The cc_max_agents from this configuration + */ +unsigned int ast_get_cc_max_agents(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the cc_max_agents + * \param config The configuration to set the cc_max_agents on + * \param value The new cc_max_agents we want to change to + * \retval void + */ +void ast_set_cc_max_agents(struct ast_cc_config_params *config, unsigned int value); + +/*! + * \since 1.8 + * \brief Get the cc_max_monitors + * \param config The configuration to retrieve the cc_max_monitors from + * \return The cc_max_monitors from this configuration + */ +unsigned int ast_get_cc_max_monitors(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the cc_max_monitors + * \param config The configuration to set the cc_max_monitors on + * \param value The new cc_max_monitors we want to change to + * \retval void + */ +void ast_set_cc_max_monitors(struct ast_cc_config_params *config, unsigned int value); + +/*! + * \since 1.8 + * \brief Get the name of the callback_macro + * \param config The configuration to retrieve the callback_macro from + * \return The callback_macro name + */ +const char *ast_get_cc_callback_macro(struct ast_cc_config_params *config); + +/*! + * \since 1.8 + * \brief Set the callback_macro name + * \param config The configuration to set the callback_macro on + * \param value The new callback macro we want to change to + * \retval void + */ +void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char * const value); + +/* END CONFIGURATION FUNCTIONS */ + +/* BEGIN AGENT/MONITOR REGISTRATION API */ + +struct ast_cc_monitor_callbacks; + +/*! + * \since 1.8 + * \brief Register a set of monitor callbacks with the core + * + * \details + * 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. + * + * \param callbacks The callbacks used by the monitor implementation + * \retval 0 Successfully registered + * \retval -1 Failure to register + */ +int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks); + +/*! + * \since 1.8 + * \brief Unregister a set of monitor callbacks with the core + * + * \details + * If a module which makes use of a CC monitor is unloaded, then it may + * unregister its monitor callbacks with the core. + * + * \param callbacks The callbacks used by the monitor implementation + * \retval 0 Successfully unregistered + * \retval -1 Failure to unregister + */ +void ast_cc_monitor_unregister(const struct ast_cc_monitor_callbacks *callbacks); + +struct ast_cc_agent_callbacks; + +/*! + * \since 1.8 + * \brief Register a set of agent callbacks with the core + * + * \details + * 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. + * + * \param callbacks The callbacks used by the agent implementation + * \retval 0 Successfully registered + * \retval -1 Failure to register + */ +int ast_cc_agent_register(const struct ast_cc_agent_callbacks *callbacks); + +/*! + * \since 1.8 + * \brief Unregister a set of agent callbacks with the core + * + * \details + * If a module which makes use of a CC agent is unloaded, then it may + * unregister its agent callbacks with the core. + * + * \param callbacks The callbacks used by the agent implementation + * \retval 0 Successfully unregistered + * \retval -1 Failure to unregister + */ +void ast_cc_agent_unregister(const struct ast_cc_agent_callbacks *callbacks); + +/* END AGENT/MONITOR REGISTRATION API */ + +/* BEGIN SECTION ON MONITORS AND MONITOR CALLBACKS */ + +/*! + * It is recommended that monitors use a pointer to + * an ast_cc_monitor_callbacks::type when creating + * an AST_CONTROL_CC frame. Since the generic monitor + * callbacks are opaque and channel drivers will wish + * to use that, this string is made globally available + * for all to use + */ +#define AST_CC_GENERIC_MONITOR_TYPE "generic" + +/*! + * Used to determine which type + * of monitor an ast_cc_device_monitor + * is. + */ +enum ast_cc_monitor_class { + AST_CC_DEVICE_MONITOR, + AST_CC_EXTENSION_MONITOR, +}; + +/*! + * \internal + * \brief An item in a CC interface tree. + * + * These are the individual items in an interface tree. + * The key difference between this structure and the ast_cc_interface + * is that this structure contains data which is intrinsic to the item's + * placement in the tree, such as who its parent is. + */ +struct ast_cc_monitor { + /*! + * Information regarding the interface. + */ + struct ast_cc_interface *interface; + /*! + * Every interface has an id that uniquely identifies it. It is + * formed by incrementing a counter. + */ + unsigned int id; + /*! + * The ID of this monitor's parent. If this monitor is at the + * top of the tree, then his parent will be 0. + */ + unsigned int parent_id; + /*! + * The instance of the CC core to which this monitor belongs + */ + int core_id; + /*! + * The type of call completion service offered by a device. + */ + enum ast_cc_service_type service_offered; + /*! + * \brief Name that should be used to recall specified interface + * + * \details + * When issuing a CC recall, some technologies will require + * that a name other than the device name is dialed. For instance, + * with SIP, a specific URI will be used which chan_sip will be able + * to recognize as being a CC recall. Similarly, ISDN will need a specific + * dial string to know that the call is a recall. + */ + char *dialstring; + /*! + * The ID of the available timer used by the current monitor + */ + int available_timer_id; + /*! + * Monitor callbacks + */ + const struct ast_cc_monitor_callbacks *callbacks; + /*! + * \brief Data that is private to a monitor technology + * + * Most channel drivers that implement CC monitors will have to + * allocate data that the CC core does not care about but which + * is vital to the operation of the monitor. This data is stored + * in this pointer so that the channel driver may use it as + * needed + */ + void *private_data; + AST_LIST_ENTRY(ast_cc_monitor) next; +}; + +/*! + * \brief Callbacks defined by CC monitors + * + * \note + * Every callback is called with the list of monitors locked. There + * are several public API calls that also will try to lock this lock. + * These public functions have a note in their doxygen stating so. + * As such, pay attention to the lock order you establish in these callbacks + * to ensure that you do not violate the lock order when calling + * the functions in this file with lock order notices. + */ +struct ast_cc_monitor_callbacks { + /*! + * \brief Type of monitor the callbacks belong to. + * + * \note + * Examples include "generic" and "SIP" + */ + const char *type; + /*! + * \brief Request CCSS. + * + * \param monitor CC core monitor control. + * \param available_timer_id The scheduler ID for the available timer. + * Will never be NULL for a device monitor. + * + * \details + * Perform whatever steps are necessary in order to request CC. + * In addition, the monitor implementation is responsible for + * starting the available timer in this callback. + * + * \retval 0 on success + * \retval -1 on failure. + */ + int (*request_cc)(struct ast_cc_monitor *monitor, int *available_timer_id); + /*! + * \brief Suspend monitoring. + * + * \param monitor CC core monitor control. + * + * \details + * Implementers must perform the necessary steps to suspend + * monitoring. + * + * \retval 0 on success + * \retval -1 on failure. + */ + int (*suspend)(struct ast_cc_monitor *monitor); + /*! + * \brief Status response to an ast_cc_monitor_status_request(). + * + * \param monitor CC core monitor control. + * \param devstate Current status of a Party A device. + * + * \details + * Alert a monitor as to the status of the agent for which + * the monitor had previously requested a status request. + * + * \note Zero or more responses may come as a result. + * + * \retval 0 on success + * \retval -1 on failure. + */ + int (*status_response)(struct ast_cc_monitor *monitor, enum ast_device_state devstate); + /*! + * \brief Unsuspend monitoring. + * + * \param monitor CC core monitor control. + * + * \details + * Perform the necessary steps to unsuspend monitoring. + * + * \retval 0 on success + * \retval -1 on failure. + */ + int (*unsuspend)(struct ast_cc_monitor *monitor); + /*! + * \brief Cancel the running available timer. + * + * \param monitor CC core monitor control. + * \param sched_id Available timer scheduler id to cancel. + * Will never be NULL for a device monitor. + * + * \details + * In most cases, this function will likely consist of just a + * call to AST_SCHED_DEL. It might have been possible to do this + * within the core, but unfortunately the mixture of sched_thread + * and sched usage in Asterisk prevents such usage. + * + * \retval 0 on success + * \retval -1 on failure. + */ + int (*cancel_available_timer)(struct ast_cc_monitor *monitor, int *sched_id); + /*! + * \brief Destroy private data on the monitor. + * + * \param private_data The private data pointer from the monitor. + * + * \details + * Implementers of this callback are responsible for destroying + * all heap-allocated data in the monitor's private_data pointer, including + * the private_data itself. + */ + void (*destructor)(void *private_data); +}; + +/*! + * \since 1.8 + * \brief Scheduler callback for available timer expiration + * + * \note + * When arming the available timer from within a device monitor, you MUST + * use this function as the callback for the scheduler. + * + * \param data A reference to the CC monitor on which the timer was running. + */ +int ast_cc_available_timer_expire(const void *data); + +/* END SECTION ON MONITORS AND MONITOR CALLBACKS */ + +/* BEGIN API FOR IN-CALL CC HANDLING */ + +/*! + * \since 1.8 + * + * \brief Mark the channel to ignore further CC activity. + * + * \details + * 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. + * + * \param chan The channel for which further CC processing should be ignored. + * \retval void + */ +void ast_ignore_cc(struct ast_channel *chan); + +/*! + * \since 1.8 + * + * \brief Properly react to a CC control frame. + * + * \details + * When a CC-capable application, such as Dial, receives a frame + * of type AST_CONTROL_CC, then it may call this function in order + * to have the device which sent the frame added to the tree of interfaces + * which is kept on the inbound channel. + * + * \param inbound The inbound channel + * \param outbound The outbound channel (The one from which the CC frame was read) + * \param frame_data The ast_frame's data.ptr field. + * \retval void + */ +void ast_handle_cc_control_frame(struct ast_channel *inbound, struct ast_channel *outbound, void *frame_data); + +/*! + * \since 1.8 + * + * \brief Start the CC process on a call. + * + * \details + * 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. + * + * \param chan The inbound channel calling the CC-capable application. + * \param[out] ignore_cc Will be set non-zero if no further CC actions need to be taken + * \retval 0 Success + * \retval -1 Failure + */ +int ast_cc_call_init(struct ast_channel *chan, int *ignore_cc); + +/*! + * \since 1.8 + * + * \brief Add a child dialstring to an extension monitor + * + * 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. + * + * \param incoming The caller's channel + * \param dialstring The dialstring used when requesting the outbound channel + * \param device_name The device name associated with the requested outbound channel + * \retval void + */ +void ast_cc_extension_monitor_add_dialstring(struct ast_channel *incoming, const char * const dialstring, const char * const device_name); + +/*! + * \since 1.8 + * \brief Check if the incoming CC request is within the bounds + * set by the cc_max_requests configuration option + * + * \details + * 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. + * + * \retval 0 Not within the limits. Fail. + * \retval non-zero Within the limits. Success. + */ +int ast_cc_request_is_within_limits(void); + +/*! + * \since 1.8 + * \brief Get the core id for the current call + * + * \details + * 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. + * + * \param chan The channel from which to get the core_id. + * \retval core_id on success + * \retval -1 Failure + */ +int ast_cc_get_current_core_id(struct ast_channel *chan); + +/* END API FOR IN-CALL CC HANDLING */ + +/*! + * \brief Structure with information about an outbound interface + * + * \details + * This structure is first created when an outbound interface indicates that + * it is capable of accepting a CC request. It is stored in a "tree" on a datastore on + * the caller's channel. Once an agent structure is created, the agent gains + * a reference to the tree of interfaces. If CC is requested, then the + * interface tree on the agent is converted into a tree of monitors. Each + * monitor will contain a pointer to an individual ast_cc_interface. Finally, + * the tree of interfaces is also present on a second datastore during a + * CC recall so that the CC_INTERFACES channel variable may be properly + * populated. + */ +struct ast_cc_interface { + /* What class of monitor is being offered here + */ + enum ast_cc_monitor_class monitor_class; + /*! + * \brief The type of monitor that should be used for this interface + * + * \details + * This will be something like "extension" "generic" or "SIP". + * This should point to a static const char *, so there is + * no reason to make a new copy. + */ + const char *monitor_type; + /*! + * The configuration parameters used for this interface + */ + struct ast_cc_config_params *config_params; + /* The name of the interface/extension. local channels will + * have 'exten@context' for a name. Other channel types will + * have 'tech/device' for a name. + */ + char device_name[1]; +}; + +/* BEGIN STRUCTURES FOR AGENTS */ + +struct ast_cc_agent { + /*! + * Which instance of the core state machine does this + * agent pertain to? + */ + unsigned int core_id; + /*! + * Callback functions needed for specific agent + * implementations + */ + const struct ast_cc_agent_callbacks *callbacks; + /*! + * Configuration parameters that affect this + * agent's operation. + */ + struct ast_cc_config_params *cc_params; + /*! + * \brief Flags for agent operation + * + * \details + * There are some attributes of certain agent types + * that can alter the behavior of certain CC functions. + * For a list of these flags, see the ast_cc_agent_flags + * enum + */ + unsigned int flags; + /*! Data specific to agent implementation */ + void *private_data; + /*! The name of the device which this agent + * represents/communicates with + */ + char device_name[1]; +}; + +struct ast_cc_agent_callbacks { + /*! + * \brief Type of agent the callbacks belong to. + * + * \note + * Examples are "SIP" "ISDN" and "generic" + */ + const char *type; + /*! + * \brief CC agent initialization. + * + * \param agent CC core agent control. + * \param chan Original channel the agent will attempt to recall. + * + * \details + * This callback is called when the CC core + * is initialized. Agents should allocate + * any private data necessary for the + * call and assign it to the private_data + * on the agent. Additionally, if any ast_cc_agent_flags + * are pertinent to the specific agent type, they should + * be set in this function as well. + * + * \retval 0 on success. + * \retval -1 on error. + */ + int (*init)(struct ast_cc_agent *agent, struct ast_channel *chan); + /*! + * \brief Start the offer timer. + * + * \param agent CC core agent control. + * + * \details + * This is called by the core when the caller hangs up after + * a call for which CC may be requested. The agent should + * begin the timer as configured. + * + * The primary reason why this functionality is left to + * the specific agent implementations is due to the differing + * use of schedulers throughout the code. Some channel drivers + * may already have a scheduler context they wish to use, and + * amongst those, some may use the ast_sched API while others + * may use the ast_sched_thread API, which are incompatible. + * + * \retval 0 on success. + * \retval -1 on error. + */ + int (*start_offer_timer)(struct ast_cc_agent *agent); + /*! + * \brief Stop the offer timer. + * + * \param agent CC core agent control. + * + * \details + * This callback is called by the CC core when the caller + * has requested CC. + * + * \retval 0 on success. + * \retval -1 on error. + */ + int (*stop_offer_timer)(struct ast_cc_agent *agent); + /*! + * \brief Acknowledge CC request. + * + * \param agent CC core agent control. + * + * \details + * When the core receives knowledge that a called + * party has accepted a CC request, it will call + * this callback. + * + * The duty of this is to accept a CC request from + * the caller by acknowledging receipt of that request. + */ + void (*ack)(struct ast_cc_agent *agent); + /*! + * \brief Request the status of the agent's device. + * + * \param agent CC core agent control. + * + * \details + * Asynchronous request for the status of any caller + * which may be a valid caller for the CC transaction. + * Status responses should be made using the + * ast_cc_status_response function. + * + * \retval 0 on success. + * \retval -1 on error. + */ + int (*status_request)(struct ast_cc_agent *agent); + /*! + * \brief Request for an agent's phone to stop ringing. + * + * \param agent CC core agent control. + * + * \details + * The usefulness of this is quite limited. The only specific + * known case for this is if Asterisk requests CC over an ISDN + * PTMP link as the TE side. If other phones are in the same + * recall group as the Asterisk server, and one of those phones + * picks up the recall notice, then Asterisk will receive a + * "stop ringing" notification from the NT side of the PTMP + * link. This indication needs to be passed to the phone + * on the other side of the Asterisk server which originally + * placed the call so that it will stop ringing. Since the + * phone may be of any type, it is necessary to have a callback + * that the core can know about. + * + * \retval 0 on success. + * \retval -1 on error. + */ + int (*stop_ringing)(struct ast_cc_agent *agent); + /*! + * \brief Let the caller know that the callee has become free + * but that the caller cannot attempt to call back because + * he is either busy or there is congestion on his line. + * + * \param agent CC core agent control. + * + * \details + * This is something that really only affects a scenario where + * a phone places a call over ISDN PTMP to Asterisk, who then + * connects over PTMP again to the ISDN network. For most agent + * types, there is no need to implement this callback at all + * because they don't really need to actually do anything in + * this situation. If you're having trouble understanding what + * the purpose of this callback is, then you can be safe simply + * not implementing it. + * + * \retval 0 on success. + * \retval -1 on error. + */ + int (*party_b_free)(struct ast_cc_agent *agent); + /*! + * \brief Begin monitoring a busy device. + * + * \param agent CC core agent control. + * + * \details + * The core will call this callback if the callee becomes + * available but the caller has reported that he is busy. + * The agent should begin monitoring the caller's device. + * When the caller becomes available again, the agent should + * call ast_cc_agent_caller_available. + * + * \retval 0 on success. + * \retval -1 on error. + */ + int (*start_monitoring)(struct ast_cc_agent *agent); + /*! + * \brief Alert the caller that it is time to try recalling. + * + * \param agent CC core agent control. + * + * \details + * The core will call this function when it receives notice + * that a monitored party has become available. + * + * The agent's job is to send a message to the caller to + * notify it of such a change. If the agent is able to + * discern that the caller is currently unavailable, then + * the agent should react by calling the ast_cc_caller_unavailable + * function. + * + * \retval 0 on success. + * \retval -1 on error. + */ + int (*callee_available)(struct ast_cc_agent *agent); + /*! + * \brief Destroy private data on the agent. + * + * \param agent CC core agent control. + * + * \details + * The core will call this function upon completion + * or failure of CC. + * + * \note + * The agent private_data pointer may be NULL if the agent + * constructor failed. + */ + void (*destructor)(struct ast_cc_agent *agent); +}; + +/*! + * \brief Call a callback on all agents of a specific type + * + * \details + * 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. + * + * \param flags astobj2 search flags + * \param function an ao2 callback function to call + * \param arg the argument to the callback function + * \param type The type of agents to call the callback on + */ +struct ast_cc_agent *ast_cc_agent_callback(int flags, ao2_callback_fn *function, void *arg, const char * const type); + +/* END STRUCTURES FOR AGENTS */ + +/* BEGIN STATE CHANGE API */ + +/*! + * \since 1.8 + * \brief Offer CC to a caller + * + * \details + * This function is called from ast_hangup if the caller is + * eligible to be offered call completion service. + * + * \param caller_chan The calling channel + * \retval -1 Error + * \retval 0 Success + */ +int ast_cc_offer(struct ast_channel *caller_chan); + +/*! + * \since 1.8 + * \brief Accept inbound CC request + * + * \details + * When a caller requests CC, this function should be called to let + * the core know that the request has been accepted. + * + * \param core_id core_id of the CC transaction + * \param debug optional string to print for debugging purposes + * \retval 0 Success + * \retval -1 Failure + */ +int __attribute__((format(printf, 2, 3))) ast_cc_agent_accept_request(int core_id, const char * const debug, ...); + +/*! + * \since 1.8 + * \brief Indicate that an outbound entity has accepted our CC request + * + * \details + * When we receive confirmation that an outbound device has accepted the + * CC request we sent it, this function must be called. + * + * \param core_id core_id of the CC transaction + * \param debug optional string to print for debugging purposes + * \retval 0 Success + * \retval -1 Failure + */ +int __attribute__((format(printf, 2, 3))) ast_cc_monitor_request_acked(int core_id, const char * const debug, ...); + +/*! + * \since 1.8 + * \brief Indicate that the caller is busy + * + * \details + * 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. + * + * \param core_id core_id of the CC transaction + * \param debug optional string to print for debugging purposes + * \retval 0 Success + * \retval -1 Failure + */ +int __attribute__((format(printf, 2, 3))) ast_cc_agent_caller_busy(int core_id, const char * const debug, ...); + +/*! + * \since 1.8 + * \brief Indicate that a previously unavailable caller has become available + * + * \details + * 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. + * + * \param core_id core_id of the CC transaction + * \param debug optional string to print for debugging purposes + * \retval 0 Success + * \retval -1 Failure + */ +int __attribute__((format(printf, 2, 3))) ast_cc_agent_caller_available(int core_id, const char * const debug, ...); + +/*! + * \since 1.8 + * \brief Tell the CC core that a caller is currently recalling + * + * \details + * 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. + * + * \param core_id core_id of the CC transaction + * \param debug optional string to print for debugging purposes + * \retval 0 Success + * \retval -1 Failure + */ +int __attribute__((format(printf, 2, 3))) ast_cc_agent_recalling(int core_id, const char * const debug, ...); + +/*! + * \since 1.8 + * \brief Indicate recall has been acknowledged + * + * \details + * When we receive confirmation that an endpoint has responded to our + * CC recall, we call this function. + * + * \param chan The inbound channel making the CC recall + * \param debug optional string to print for debugging purposes + * \retval 0 Success + * \retval -1 Failure + */ +int __attribute__((format(printf, 2, 3))) ast_cc_completed(struct ast_channel *chan, const char * const debug, ...); + +/*! + * \since 1.8 + * \brief Indicate failure has occurred + * + * \details + * If at any point a failure occurs, this is the function to call + * so that the core can initiate cleanup procedures. + * + * \param core_id core_id of the CC transaction + * \param debug optional string to print for debugging purposes + * \retval 0 Success + * \retval -1 Failure + */ +int __attribute__((format(printf, 2, 3))) ast_cc_failed(int core_id, const char * const debug, ...); + +/*! + * \since 1.8 + * \brief Indicate that a failure has occurred on a specific monitor + * + * \details + * 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. + * + * \param core_id The core ID for the CC transaction + * \param monitor_name The name of the monitor on which the failure occurred + * \param debug A debug message to print to the CC log + * \return void + */ +int __attribute__((format(printf, 3, 4))) ast_cc_monitor_failed(int core_id, const char * const monitor_name, const char * const debug, ...); + +/* END STATE CHANGE API */ + +/*! + * 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. + */ + +/*! + * \brief Request the status of a caller or callers. + * + * \details + * 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. + * + * \param core_id The core ID of the CC transaction + * + * \retval 0 Successfully requested status + * \retval -1 Failed to request status + */ +int ast_cc_monitor_status_request(int core_id); + +/*! + * \brief Response with a caller's current status + * + * \details + * 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. + * + * \param core_id The core ID of the CC transaction + * \param devstate The current state of the caller to which the agent pertains + * \retval 0 Successfully responded with our status + * \retval -1 Failed to respond with our status + */ +int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate); + +/*! + * \brief Alert a caller to stop ringing + * + * \details + * 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. + * + * \param core_id The core ID of the CC transaction + * \retval 0 Successfully requested for the phone to stop ringing + * \retval -1 Could not request for the phone to stop ringing + */ +int ast_cc_monitor_stop_ringing(int core_id); + +/*! + * \brief Alert a caller that though the callee has become free, the caller + * himself is not and may not call back. + * + * \details + * 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. + * + * \param core_id The core ID of the CC transaction + * \retval 0 Successfully alerted the core that party B is free + * \retval -1 Could not alert the core that party B is free + */ +int ast_cc_monitor_party_b_free(int core_id); + +/* BEGIN API FOR USE WITH/BY MONITORS */ + +/*! + * \since 1.8 + * \brief Return the number of outstanding CC requests to a specific device + * + * \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. + * + * \param name The name of the monitored device + * \param type The type of the monitored device (e.g. "generic") + * \return The number of CC requests for the monitor + */ +int ast_cc_monitor_count(const char * const name, const char * const type); + +/*! + * \since 1.8 + * \brief Alert the core that a device being monitored has become available. + * + * \note + * The code in the core will take care of making sure that the information gets passed + * up the ladder correctly. + * + * \param core_id The core ID of the corresponding CC transaction + * \retval 0 Request successfully queued + * \retval -1 Request could not be queued + */ +int __attribute__((format(printf, 2, 3))) ast_cc_monitor_callee_available(const int core_id, const char * const debug, ...); + +/* END API FOR USE WITH/BY MONITORS */ + +/* BEGIN API TO BE USED ON CC RECALL */ + +/*! + * \since 1.8 + * \brief Set up a CC recall datastore on a channel + * + * \details + * 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. + */ +int ast_setup_cc_recall_datastore(struct ast_channel *chan, const int core_id); + +/*! + * \since 1.8 + * \brief Decide if a call to a particular channel is a CC recall + * + * \details + * 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. + * + * \note + * 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. + * + * \param chan The channel to check + * \param core_id[out] If this is a valid CC recall, the core_id of the failed call + * will be placed in this output parameter + * \param monitor_type Clarify 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. + * \retval 0 Either this is not a recall or it is but this channel is not part of the recall + * \retval non-zero This is a recall and the channel in question is directly involved. + */ +int ast_cc_is_recall(struct ast_channel *chan, int *core_id, const char * const monitor_type); + +/*! + * \since 1.8 + * \brief Get the associated monitor given the device name and core_id + * + * \details + * 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. + * + * \param core_id The core ID to which this recall corresponds. This likely will + * have been obtained using the ast_cc_is_recall function + * \param device_name Which device to find the monitor for. + * + * \retval NULL Appropriate monitor does not exist + * \retval non-NULL The monitor to use for this recall + */ +struct ast_cc_monitor *ast_cc_get_monitor_by_recall_core_id(const int core_id, const char * const device_name); + +/*! + * \since 1.8 + * \brief Set the first level CC_INTERFACES channel variable for a channel. + * + * \note + * Implementers of protocol-specific CC agents should call this function after + * calling ast_setup_cc_recall_datastore. + * + * \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. + * + * \details + * The CC_INTERFACES channel variable will have the interfaces that should be + * called back for a specific PBX instance. + * + * \param chan The channel to set the CC_INTERFACES variable on + */ +int ast_cc_agent_set_interfaces_chanvar(struct ast_channel *chan); + +/*! + * \since 1.8 + * \brief Set the CC_INTERFACES channel variable for a channel using an + * extension@context as a starting point + * + * \details + * 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. + * + * \param chan The channel to set the CC_INTERFACES variable on + * \param extension The name of the extension for which we're setting the variable. + * This should be in the form of "exten@context" + */ +int ast_set_cc_interfaces_chanvar(struct ast_channel *chan, const char * const extension); + +/*! + * \since 1.8 + * \brief Make CCBS available in the case that ast_call fails + * + * 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. + */ +void ast_cc_call_failed(struct ast_channel *incoming, struct ast_channel *outgoing, const char * const dialstring); + +/*! + * \since 1.8 + * \brief Callback made from ast_cc_callback for certain channel types + * + * \param inbound Incoming asterisk channel. + * \param cc_params The CC configuration parameters for the outbound target + * \param monitor_type The type of monitor to use when CC is requested + * \param device_name The name of the outbound target device. + * \param dialstring The dial string used when calling this specific interface + * \param private_data If 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. + * + * \details + * 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. + */ +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); + +/*! + * \since 1.8 + * \brief Create a CC Control frame + * + * \details + * 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. + * + * \param chan A channel involved in the call. What we want is on a datastore on both incoming and outgoing so either may be provided + * \param cc_params The CC configuration parameters for the outbound target + * \param monitor_type The type of monitor to use when CC is requested + * \param device_name The name of the outbound target device. + * \param dialstring The dial string used when calling this specific interface + * \param service What kind of CC service is being offered. (CCBS/CCNR/etc...) + * \param private_data If 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. + * \param[out] frame. The 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. + * \retval -1 Failure. At some point there was a failure. Do not attempt to use the frame in this case. + * \retval 0 Success + */ +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); + + +/*! + * \brief Callback made from ast_cc_callback for certain channel types + * \since 1.8 + * + * \param chan A channel involved in the call. What we want is on a datastore on both incoming and outgoing so either may be provided + * \param cc_params The CC configuration parameters for the outbound target + * \param monitor_type The type of monitor to use when CC is requested + * \param device_name The name of the outbound target device. + * \param dialstring The dial string used when calling this specific interface + * \param private_data If 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. + * + * \details + * 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. + * + * \return Nothing + */ +typedef void (*ast_cc_callback_fn)(struct ast_channel *chan, struct ast_cc_config_params *cc_params, + const char *monitor_type, const char * const device_name, const char * const dialstring, void *private_data); + +/*! + * \since 1.8 + * \brief Run a callback for potential matching destinations. + * + * \note + * See the explanation in ast_channel_tech::cc_callback for more + * details. + * + * \param tech Channel technology to use + * \param dest Channel/group/peer or whatever the specific technology uses + * \param callback Function to call when a target is reached + * \retval Always 0, I guess. + */ +int ast_cc_callback(struct ast_channel *inbound, const char * const tech, const char * const dest, ast_cc_callback_fn callback); + +/*! + * \since 1.8 + * \brief Initialize CCSS + * + * Performs startup routines necessary for CC operation. + * + * \retval 0 Success + * \retval nonzero Failure + */ +int ast_cc_init(void); + +#endif /* _ASTERISK_CCSS_H */ |