Merge Call completion support into trunk.

From Reviewboard:
CCSS stands for Call Completion Supplementary Services. An admittedly out-of-date
overview of the architecture can be found in the file doc/CCSS_architecture.pdf
in the CCSS branch. Off the top of my head, the big differences between what is
implemented and what is in the document are as follows:

1. We did not end up modifying the Hangup application at all.
2. The document states that a single call completion monitor may be used across
   multiple calls to the same device. This proved to not be such a good idea
   when implementing protocol-specific monitors, and so we ended up using one
   monitor per-device per-call.
3. There are some configuration options which were conceived after the document
   was written. These are documented in the ccss.conf.sample that is on this
   review request.
		      
For some basic understanding of terminology used throughout this code, see the
ccss.tex document that is on this review.

This implements CCBS and CCNR in several flavors.

First up is a "generic" implementation, which can work over any channel technology
provided that the channel technology can accurately report device state. Call
completion is requested using the dialplan application CallCompletionRequest and can
be canceled using CallCompletionCancel. Device state subscriptions are used in order
to monitor the state of called parties.

Next, there is a SIP-specific implementation of call completion. This method uses the
methods outlined in draft-ietf-bliss-call-completion-06 to implement call completion
using SIP signaling. There are a few things to note here:

* The agent/monitor terminology used throughout Asterisk sometimes is the reverse of
  what is defined in the referenced draft.

* Implementation of the draft required support for SIP PUBLISH. I attempted to write
  this in a generic-enough fashion such that if someone were to want to write PUBLISH
  support for other event packages, such as dialog-state or presence, most of the effort
  would be in writing callbacks specific to the event package.

* A subportion of supporting PUBLISH reception was that we had to implement a PIDF
  parser. The PIDF support added is a bit minimal. I first wrote a validation
  routine to ensure that the PIDF document is formatted properly. The rest of the
  PIDF reading is done in-line in the call-completion-specific PUBLISH-handling
  code. In other words, while there is PIDF support here, it is not in any state
  where it could easily be applied to other event packages as is.

Finally, there are a variety of ISDN-related call completion protocols supported. These
were written by Richard Mudgett, and as such I can't really say much about their
implementation. There are notes in the CHANGES file that indicate the ISDN protocols
over which call completion is supported.

Review: https://reviewboard.asterisk.org/r/523


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@256528 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Michelson
2010-04-09 15:31:32 +00:00
parent 6cad0f1602
commit e24661fd18
30 changed files with 11612 additions and 233 deletions

1582
include/asterisk/ccss.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -148,6 +148,8 @@ extern "C" {
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/datastore.h"
#include "asterisk/channelstate.h"
#include "asterisk/ccss.h"
#define DATASTORE_INHERIT_FOREVER INT_MAX
@@ -507,6 +509,29 @@ struct ast_channel_tech {
/*! \brief Get the unique identifier for the PVT, i.e. SIP call-ID for SIP */
const char * (* get_pvt_uniqueid)(struct ast_channel *chan);
/*! \brief Call a function with cc parameters as a function parameter
*
* \details
* This is a highly specialized callback that is not likely to be needed in many
* channel drivers. When dealing with a busy channel, for instance, most channel
* drivers will successfully return a channel to the requester. Once called, the channel
* can then queue a busy frame when it receives an appropriate message from the far end.
* In such a case, the channel driver has the opportunity to also queue a CC frame.
* The parameters for the CC channel can be retrieved from the channel structure.
*
* For other channel drivers, notably those that deal with "dumb" phones, the channel
* driver will not return a channel when one is requested. In such a scenario, there is never
* an opportunity for the channel driver to queue a CC frame since the channel is never
* called. Furthermore, it is not possible to retrieve the CC configuration parameters
* for the desired channel because no channel is ever allocated or returned to the
* requester. In such a case, call completion may still be a viable option. What we do is
* pass the same string that the requester used originally to request the channel to the
* channel driver. The channel driver can then find any potential channels/devices that
* match the input and return call the designated callback with the device's call completion
* parameters as a parameter.
*/
int (* cc_callback)(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
};
struct ast_epoll_data;
@@ -534,27 +559,6 @@ enum ast_channel_adsicpe {
AST_ADSI_OFFHOOKONLY,
};
/*!
* \brief ast_channel states
*
* \note Bits 0-15 of state are reserved for the state (up/down) of the line
* Bits 16-32 of state are reserved for flags
*/
enum ast_channel_state {
AST_STATE_DOWN, /*!< Channel is down and available */
AST_STATE_RESERVED, /*!< Channel is down, but reserved */
AST_STATE_OFFHOOK, /*!< Channel is off hook */
AST_STATE_DIALING, /*!< Digits (or equivalent) have been dialed */
AST_STATE_RING, /*!< Line is ringing */
AST_STATE_RINGING, /*!< Remote end is ringing */
AST_STATE_UP, /*!< Line is up */
AST_STATE_BUSY, /*!< Line is busy */
AST_STATE_DIALING_OFFHOOK, /*!< Digits (or equivalent) have been dialed while offhook */
AST_STATE_PRERING, /*!< Channel has detected an incoming call and is waiting for ring */
AST_STATE_MUTE = (1 << 16), /*!< Do not transmit voice data */
};
/*!
* \brief Possible T38 states on channels
*/
@@ -950,9 +954,6 @@ int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore
*/
struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid);
/*! \brief Change the state of a channel */
int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
/*!
* \brief Create a channel structure
* \since 1.8
@@ -2756,6 +2757,95 @@ void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct
* '0'
*/
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame);
#include "asterisk/ccss.h"
/*!
* \since 1.8
* \brief Set up datastore with CCSS parameters for a channel
*
* \note
* If base_params is NULL, the channel will get the default
* values for all CCSS parameters.
*
* \details
* This function makes use of datastore operations on the channel, so
* it is important to lock the channel before calling this function.
*
* \param chan The channel to create the datastore on
* \param base_params CCSS parameters we wish to copy into the channel
* \retval 0 Success
* \retval -1 Failure
*/
int ast_channel_cc_params_init(struct ast_channel *chan,
const struct ast_cc_config_params *base_params);
/*!
* \since 1.8
* \brief Get the CCSS parameters from a channel
*
* \details
* This function makes use of datastore operations on the channel, so
* it is important to lock the channel before calling this function.
*
* \param chan Channel to retrieve parameters from
* \retval NULL Failure
* \retval non-NULL The parameters desired
*/
struct ast_cc_config_params *ast_channel_get_cc_config_params(struct ast_channel *chan);
/*!
* \since 1.8
* \brief Get a device name given its channel structure
*
* \details
* A common practice in Asterisk is to determine the device being talked
* to by dissecting the channel name. For certain channel types, this is not
* accurate. For instance, an ISDN channel is named based on what B channel is
* used, not the device being communicated with.
*
* This function interfaces with a channel tech's queryoption callback to
* retrieve the name of the device being communicated with. If the channel does not
* implement this specific option, then the traditional method of using the channel
* name is used instead.
*
* \param chan The channel to retrieve the information from
* \param device_name[out] The buffer to place the device's name into
* \param name_buffer_length The allocated space for the device_name
* \return 0 always
*/
int ast_channel_get_device_name(struct ast_channel *chan, char *device_name, size_t name_buffer_length);
/*!
* \since 1.8
* \brief Find the appropriate CC agent type to use given a channel
*
* \details
* During call completion, we will need to create a call completion agent structure. To
* figure out the type of agent to construct, we need to ask the channel driver for the
* appropriate type.
*
* Prior to adding this function, the call completion core attempted to figure this
* out for itself by stripping the technology off the channel's name. However, in the
* case of chan_dahdi, there are multiple agent types registered, and so simply searching
* for an agent type called "DAHDI" is not possible. In a case where multiple agent types
* are defined, the channel driver must have a queryoption callback defined in its
* channel_tech, and the queryoption callback must handle AST_OPTION_CC_AGENT_TYPE
*
* If a channel driver does not have a queryoption callback or if the queryoption callback
* does not handle AST_OPTION_CC_AGENT_TYPE, then the old behavior of using the technology
* portion of the channel name is used instead. This is perfectly suitable for channel drivers
* whose channel technologies are a one-to-one match with the agent types defined within.
*
* Note that this function is only called when the agent policy on a given channel is set
* to "native." Generic agents' type can be determined automatically by the core.
*
* \param chan The channel for which we wish to retrieve the agent type
* \param[out] agent_type The type of agent the channel driver wants us to use
* \param size The size of the buffer to write to
*/
int ast_channel_get_cc_agent_type(struct ast_channel *chan, char *agent_type, size_t size);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

View File

@@ -0,0 +1,53 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2010, Digium, Inc.
*
* 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 Channel states
* \par See also:
* \arg \ref Def_Channel
* \arg \ref channel_drivers
*/
#ifndef __AST_CHANNELSTATE_H__
#define __AST_CHANNELSTATE_H__
#include "asterisk.h"
/*!
* \brief ast_channel states
*
* \note Bits 0-15 of state are reserved for the state (up/down) of the line
* Bits 16-32 of state are reserved for flags
*/
enum ast_channel_state {
AST_STATE_DOWN, /*!< Channel is down and available */
AST_STATE_RESERVED, /*!< Channel is down, but reserved */
AST_STATE_OFFHOOK, /*!< Channel is off hook */
AST_STATE_DIALING, /*!< Digits (or equivalent) have been dialed */
AST_STATE_RING, /*!< Line is ringing */
AST_STATE_RINGING, /*!< Remote end is ringing */
AST_STATE_UP, /*!< Line is up */
AST_STATE_BUSY, /*!< Line is busy */
AST_STATE_DIALING_OFFHOOK, /*!< Digits (or equivalent) have been dialed while offhook */
AST_STATE_PRERING, /*!< Channel has detected an incoming call and is waiting for ring */
AST_STATE_MUTE = (1 << 16), /*!< Do not transmit voice data */
};
/*! \brief Change the state of a channel */
int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
#endif /* __AST_CHANNELSTATE_H__ */

View File

@@ -37,7 +37,7 @@
#ifndef _ASTERISK_DEVICESTATE_H
#define _ASTERISK_DEVICESTATE_H
#include "asterisk/channel.h"
#include "asterisk/channelstate.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {

View File

@@ -324,7 +324,8 @@ enum ast_control_frame_type {
AST_CONTROL_CONNECTED_LINE = 22,/*!< Indicate connected line has changed */
AST_CONTROL_REDIRECTING = 23, /*!< Indicate redirecting id has changed */
AST_CONTROL_T38_PARAMETERS = 24, /*! T38 state change request/notification with parameters */
AST_CONTROL_SRCCHANGE = 25, /*!< Media source has changed and requires a new RTP SSRC */
AST_CONTROL_CC = 25, /*!< Indication that Call completion service is possible */
AST_CONTROL_SRCCHANGE = 26, /*!< Media source has changed and requires a new RTP SSRC */
};
enum ast_control_t38 {
@@ -433,6 +434,12 @@ enum ast_control_transfer {
/*! Get or set the fax tone detection state of the channel */
#define AST_OPTION_FAX_DETECT 15
/*! Get the device name from the channel */
#define AST_OPTION_DEVICE_NAME 16
/*! Get the CC agent type from the channel */
#define AST_OPTION_CC_AGENT_TYPE 17
struct oprmode {
struct ast_channel *peer;
int mode;

View File

@@ -82,6 +82,7 @@
#define EVENT_FLAG_ORIGINATE (1 << 12) /* Originate a call to an extension */
#define EVENT_FLAG_AGI (1 << 13) /* AGI events */
#define EVENT_FLAG_HOOKRESPONSE (1 << 14) /* Hook Response */
#define EVENT_FLAG_CC (1 << 15) /* Call Completion events */
/*@} */
/*! \brief Export manager structures */

View File

@@ -70,6 +70,7 @@ extern "C" {
#endif
#include "asterisk/astobj2.h"
#include "asterisk/frame.h"
/* Maximum number of payloads supported */
#define AST_RTP_MAX_PT 256

View File

@@ -45,6 +45,14 @@ int ast_xml_finish(void);
*/
struct ast_xml_doc *ast_xml_open(char *filename);
/*! \brief Open an XML document that resides in memory.
* \param buffer The address where the document is stored
* \size The number of bytes in the document
* \retval NULL on error.
* \retval The ast_xml_doc reference to the open document.
*/
struct ast_xml_doc *ast_xml_read_memory(char *buffer, size_t size);
/*! \brief Close an already open document and free the used
* structure.
* \retval doc The document reference.
@@ -90,6 +98,8 @@ const char *ast_xml_get_attribute(struct ast_xml_node *node, const char *attrnam
* \retval The node on success.
*/
struct ast_xml_node *ast_xml_find_element(struct ast_xml_node *root_node, const char *name, const char *attrname, const char *attrvalue);
struct ast_xml_ns *ast_xml_find_namespace(struct ast_xml_doc *doc, struct ast_xml_node *node, const char *ns_name);
const char *ast_xml_get_ns_href(struct ast_xml_ns *ns);
/*! \brief Get an element content string.
* \param node Node from where to get the string.