summaryrefslogtreecommitdiff
path: root/include/asterisk
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2013-06-17 03:00:38 +0000
committerMatthew Jordan <mjordan@digium.com>2013-06-17 03:00:38 +0000
commit6258bbe7bd1885ac5dec095ed0c4490c83a99f44 (patch)
treeff2794f730ca55903a09b9fe7f73f45169a71386 /include/asterisk
parent67e35c7b4748c3cef954820a2b182e2a5edf8d98 (diff)
Update Asterisk's CDRs for the new bridging framework
This patch is the initial push to update Asterisk's CDR engine for the new bridging framework. This patch guts the existing CDR engine and builds the new on top of messages coming across Stasis. As changes in channel state and bridge state are detected, CDRs are built and dispatched accordingly. This fundamentally changes CDRs in a few ways. (1) CDRs are now *very* reflective of the actual state of channels and bridges. This means CDRs track well with what an actual channel is doing - which is useful in transfer scenarios (which were previously difficult to pin down). It does, however, mean that CDRs cannot be 'fooled'. Previous behavior in Asterisk allowed for CDR applications, channels, and other properties to be spoofed in parts of the code - this no longer works. (2) CDRs have defined behavior in multi-party scenarios. This behavior will not be what everyone wants, but it is a defined behavior and as such, it is predictable. (3) The CDR manipulation functions and applications have been overhauled. Major changes have been made to ResetCDR and ForkCDR in particular. Many of the options for these two applications no longer made any sense with the new framework and the (slightly) more immutable nature of CDRs. There are a plethora of other changes. For a full description of CDR behavior, see the CDR specification on the Asterisk wiki. (closes issue ASTERISK-21196) Review: https://reviewboard.asterisk.org/r/2486/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@391947 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'include/asterisk')
-rw-r--r--include/asterisk/bridging.h31
-rw-r--r--include/asterisk/cdr.h649
-rw-r--r--include/asterisk/cel.h25
-rw-r--r--include/asterisk/channel.h111
-rw-r--r--include/asterisk/channel_internal.h4
-rw-r--r--include/asterisk/stasis_channels.h60
-rw-r--r--include/asterisk/stasis_internal.h69
-rw-r--r--include/asterisk/test.h73
-rw-r--r--include/asterisk/time.h11
9 files changed, 653 insertions, 380 deletions
diff --git a/include/asterisk/bridging.h b/include/asterisk/bridging.h
index 9d3f5b3cf..0bfcc3254 100644
--- a/include/asterisk/bridging.h
+++ b/include/asterisk/bridging.h
@@ -1032,6 +1032,37 @@ void ast_bridge_change_state(struct ast_bridge_channel *bridge_channel, enum ast
int ast_bridge_queue_action(struct ast_bridge *bridge, struct ast_frame *action);
/*!
+ * \brief Update the linkedid for all channels in a bridge
+ * \since 12.0.0
+ *
+ * \param bridge The bridge to update the linkedids on
+ * \param bridge_channel The channel joining the bridge
+ * \param swap The channel being swapped out of the bridge. May be NULL.
+ *
+ * \note The bridge must be locked prior to calling this function.
+ * \note This API call is meant for internal bridging operations.
+ */
+void ast_bridge_update_linkedids(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
+
+/*!
+ * \brief Update the accountcodes for a channel entering a bridge
+ * \since 12.0.0
+ *
+ * This function updates the accountcode and peeraccount on channels in two-party
+ * bridges. In multi-party bridges, peeraccount is not set - it doesn't make much sense -
+ * however accountcode propagation will still occur if the channel joining has an
+ * accountcode.
+ *
+ * \param bridge The bridge to update the accountcodes in
+ * \param bridge_channel The channel joining the bridge
+ * \param swap The channel being swapped out of the bridge. May be NULL.
+ *
+ * \note The bridge must be locked prior to calling this function.
+ * \note This API call is meant for internal bridging operations.
+ */
+void ast_bridge_update_accountcodes(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
+
+/*!
* \brief Write a frame to the specified bridge_channel.
* \since 12.0.0
*
diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h
index c2268e312..548ca994d 100644
--- a/include/asterisk/cdr.h
+++ b/include/asterisk/cdr.h
@@ -26,33 +26,216 @@
#ifndef _ASTERISK_CDR_H
#define _ASTERISK_CDR_H
-#include <sys/time.h>
+#include "asterisk/channel.h"
+
+/*! \file
+ *
+ * \since 12
+ *
+ * \brief Call Detail Record Engine.
+ *
+ * \page CDR Call Detail Record Engine
+ *
+ * \par Intro
+ *
+ * The Call Detail Record (CDR) engine uses the \ref stasis Stasis Message Bus
+ * to build records for the channels in Asterisk. As the state of a channel and
+ * the bridges it participates in changes, notifications are sent over the
+ * Stasis Message Bus. The CDR engine consumes these notifications and builds
+ * records that reflect that state. Over the lifetime of a channel, many CDRs
+ * may be generated for that channel or that involve that channel.
+ *
+ * CDRs have a lifecycle that is a subset of the channel that they reflect. A
+ * single CDR for a channel represents a path of communication between the
+ * endpoint behind a channel and Asterisk, or between two endpoints. When a
+ * channel establishes a new path of communication, a new CDR is created for the
+ * channel. Likewise, when a path of communication is terminated, a CDR is
+ * finalized. Finally, when a channel is no longer present in Asterisk, all CDRs
+ * for that channel are dispatched for recording.
+ *
+ * Dispatching of CDRs occurs to registered CDR backends. CDR backends register
+ * through \ref ast_cdr_register and are responsible for taking the produced
+ * CDRs and storing them in permanent storage.
+ *
+ * \par CDR attributes
+ *
+ * While a CDR can have many attributes, all CDRs have two parties: a Party A
+ * and a Party B. The Party A is \em always the channel that owns the CDR. A CDR
+ * may or may not have a Party B, depending on its state.
+ *
+ * For the most part, attributes on a CDR are reflective of those same
+ * attributes on the channel at the time when the CDR was finalized. Specific
+ * CDR attributes include:
+ * \li \c start The time when the CDR was created
+ * \li \c answer The time when the Party A was answered, or when the path of
+ * communication between Party A and Party B was established
+ * \li \c end The time when the CDR was finalized
+ * \li \c duration \c end - \c start. If \c end is not known, the current time
+ * is used
+ * \li \c billsec \c end - \c answer. If \c end is not known, the current time
+ * is used
+ * \li \c userfield User set data on some party in the CDR
+ *
+ * Note that \c accountcode and \c amaflags are actually properties of a
+ * channel, not the CDR.
+ *
+ * \par CDR States
+ *
+ * CDRs go through various states during their lifetime. State transitions occur
+ * due to messages received over the \ref stasis Stasis Message Bus. The
+ * following describes the possible states a CDR can be in, and how it
+ * transitions through the states.
+ *
+ * \par Single
+ *
+ * When a CDR is created, it is put into the Single state. The Single state
+ * represents a CDR for a channel that has no Party B. CDRs can be unanswered
+ * or answered while in the Single state.
+ *
+ * The following transitions can occur while in the Single state:
+ * \li If a \ref ast_channel_dial_type indicating a Dial Begin is received, the
+ * state transitions to Dial
+ * \li If a \ref ast_channel_snapshot is received indicating that the channel
+ * has hung up, the state transitions to Finalized
+ * \li If a \ref ast_bridge_blob_type is received indicating a Bridge Enter, the
+ * state transitions to Bridge
+ *
+ * \par Dial
+ *
+ * This state represents a dial that is occurring within Asterisk. The Party A
+ * can either be the caller for a two party dial, or it can be the dialed party
+ * if the calling party is Asterisk (that is, an Originated channel). In the
+ * first case, the Party B is \em always the dialed channel; in the second case,
+ * the channel is not considered to be a "dialed" channel as it is alone in the
+ * dialed operation.
+ *
+ * While in the Dial state, multiple CDRs can be created for the Party A if a
+ * parallel dial occurs. Each dialed party receives its own CDR with Party A.
+ *
+ * The following transitions can occur while in the Dial state:
+ * \li If a \ref ast_channel_dial_type indicating a Dial End is received where
+ * the \ref dial_status is not ANSWER, the state transitions to Finalized
+ * \li If a \ref ast_channel_snapshot is received indicating that the channel
+ * has hung up, the state transitions to Finalized
+ * \li If a \ref ast_channel_dial_type indicating a Dial End is received where
+ * the \ref dial_status is ANSWER, the state transitions to DialedPending
+ * \li If a \ref ast_bridge_blob_type is received indicating a Bridge Enter, the
+ * state transitions to Bridge
+ *
+ * \par DialedPending
+ *
+ * Technically, after being dialed, a CDR does not have to transition to the
+ * Bridge state. If the channel being dialed was originated, the channel may
+ * being executing dialplan. Strangely enough, it is also valid to have both
+ * Party A and Party B - after a dial - to not be bridged and instead execute
+ * dialplan. DialedPending handles the state where we figure out if the CDR
+ * showing the dial needs to move to the Bridge state; if the CDR should show
+ * that we started executing dialplan; of if we need a new CDR.
+ *
+ * The following transition can occur while in the DialedPending state:
+ * \li If a \ref ast_channel_snapshot is received that indicates that the
+ * channel has begun executing dialplan, we transition to the Finalized state
+ * if we have a Party B. Otherwise, we transition to the Single state.
+ * \li If a \ref ast_bridge_blob_type is received indicating a Bridge Enter, the
+ * state transitions to Bridge (through the Dial state)
+ *
+ * \par Bridge
+ *
+ * The Bridge state represents a path of communication between Party A and one
+ * or more other parties. When a CDR enters into the Bridge state, the following
+ * occurs:
+ * \li The CDR attempts to find a Party B. If the CDR has a Party B, it looks
+ * for that channel in the bridge and updates itself accordingly. If the CDR
+ * does not yet have a Party B, it attempts to find a channel that can be its
+ * Party B. If it finds one, it updates itself; otherwise, the CDR is
+ * temporarily finalized.
+ * \li Once the CDR has a Party B or it is determined that it cannot have a
+ * Party B, new CDRs are created for each pairing of channels with the CDR's
+ * Party A.
+ *
+ * As an example, consider the following:
+ * \li A Dials B - both answer
+ * \li B joins a bridge. Since no one is in the bridge and it was a dialed
+ * channel, it cannot have a Party B.
+ * \li A joins the bridge. Since A's Party B is B, A updates itself with B.
+ * \li Now say an Originated channel, C, joins the bridge. The bridge becomes
+ * a multi-party bridge.
+ * \li C attempts to get a Party B. A cannot be C's Party B, as it was created
+ * before it. B is a dialed channel and can thus be C's Party B, so C's CDR
+ * updates its Party B to B.
+ * \li New CDRs are now generated. A gets a new CDR for A -> C. B is dialed, and
+ * hence cannot get any CDR.
+ * \li Now say another Originated channel, D, joins the bridge. Say D has the
+ * \ref party_a flag set on it, such that it is always the preferred Party A.
+ * As such, it takes A as its Party B.
+ * \li New CDRs are generated. D gets new CDRs for D -> B and D -> C.
+ *
+ * The following transitions can occur while in the Bridge state:
+ * \li If a \ref ast_bridge_blob_type message indicating a leave is received,
+ * the state transitions to the Pending state
+ *
+ * \par Pending
+ *
+ * After a channel leaves a bridge, we often don't know what's going to happen
+ * to it. It can enter another bridge; it can be hung up; it can continue on
+ * in the dialplan. It can even enter into limbo! Pending holds the state of the
+ * CDR until we get a subsequent Stasis message telling us what should happen.
+ *
+ * The following transitions can occur while in the Pending state:
+ * \li If a \ref ast_bridge_blob_type message is received, a new CDR is created
+ * and it is transitioned to the Bridge state
+ * \li If a \ref ast_channel_dial_type indicating a Dial Begin is received, a
+ * new CDR is created and it is transitioned to the Dial state
+ * \li If a \ref ast_channel_cache_update is received indicating a change in
+ * Context/Extension/Priority, a new CDR is created and transitioned to the
+ * Single state. If the update indicates that the party has been hung up, the
+ * CDR is transitioned to the Finalized state.
+ *
+ * \par Finalized
+ *
+ * Once a CDR enters the finalized state, it is finished. No further updates
+ * can be made to the party information, and the CDR cannot be changed.
+ *
+ * One exception to this occurs during linkedid propagation, in which the CDRs
+ * linkedids are updated based on who the channel is bridged with. In general,
+ * however, a finalized CDR is waiting for dispatch to the CDR backends.
+ */
+
+/*! \brief CDR engine settings */
+enum ast_cdr_settings {
+ CDR_ENABLED = 1 << 0, /*< Enable CDRs */
+ CDR_BATCHMODE = 1 << 1, /*< Whether or not we should dispatch CDRs in batches */
+ CDR_UNANSWERED = 1 << 2, /*< Log unanswered CDRs */
+ CDR_CONGESTION = 1 << 3, /*< Treat congestion as if it were a failed call */
+ CDR_END_BEFORE_H_EXTEN = 1 << 4, /*< End the CDR before the 'h' extension runs */
+ CDR_INITIATED_SECONDS = 1 << 5, /*< Include microseconds into the billing time */
+ CDR_DEBUG = 1 << 6, /*< Enables extra debug statements */
+};
-#include "asterisk/data.h"
+/*! \brief CDR Batch Mode settings */
+enum ast_cdr_batch_mode_settings {
+ BATCH_MODE_SCHEDULER_ONLY = 1 << 0, /*< Don't spawn a thread to handle the batches - do it on the scheduler */
+ BATCH_MODE_SAFE_SHUTDOWN = 1 << 1, /*< During safe shutdown, submit the batched CDRs */
+};
/*!
- * \brief CDR Flags
+ * \brief CDR manipulation options. Certain function calls will manipulate the
+ * state of a CDR object based on these flags.
*/
-enum {
- AST_CDR_FLAG_KEEP_VARS = (1 << 0),
- AST_CDR_FLAG_POSTED = (1 << 1),
- AST_CDR_FLAG_LOCKED = (1 << 2),
- AST_CDR_FLAG_CHILD = (1 << 3),
- AST_CDR_FLAG_POST_DISABLED = (1 << 4),
- AST_CDR_FLAG_BRIDGED = (1 << 5),
- AST_CDR_FLAG_MAIN = (1 << 6),
- AST_CDR_FLAG_ENABLE = (1 << 7),
- AST_CDR_FLAG_ANSLOCKED = (1 << 8),
- AST_CDR_FLAG_DONT_TOUCH = (1 << 9),
- AST_CDR_FLAG_POST_ENABLE = (1 << 10),
- AST_CDR_FLAG_DIALED = (1 << 11),
- AST_CDR_FLAG_ORIGINATED = (1 << 12),
+enum ast_cdr_options {
+ AST_CDR_FLAG_KEEP_VARS = (1 << 0), /*< Copy variables during the operation */
+ AST_CDR_FLAG_DISABLE = (1 << 1), /*< Disable the current CDR */
+ AST_CDR_FLAG_DISABLE_ALL = (3 << 1), /*< Disable the CDR and all future CDRs */
+ AST_CDR_FLAG_PARTY_A = (1 << 3), /*< Set the channel as party A */
+ AST_CDR_FLAG_FINALIZE = (1 << 4), /*< Finalize the current CDRs */
+ AST_CDR_FLAG_SET_ANSWER = (1 << 5), /*< If the channel is answered, set the answer time to now */
+ AST_CDR_FLAG_RESET = (1 << 6), /*< If set, set the start and answer time to now */
};
/*!
* \brief CDR Flags - Disposition
*/
-enum {
+enum ast_cdr_disposition {
AST_CDR_NOANSWER = 0,
AST_CDR_NULL = (1 << 0),
AST_CDR_FAILED = (1 << 1),
@@ -61,21 +244,16 @@ enum {
AST_CDR_CONGESTION = (1 << 4),
};
-/*!
- * \brief CDR AMA Flags
- */
-enum {
- AST_CDR_OMIT = 1,
- AST_CDR_BILLING = 2,
- AST_CDR_DOCUMENTATION = 3,
-};
-
-#define AST_MAX_USER_FIELD 256
-#define AST_MAX_ACCOUNT_CODE 20
-/* Include channel.h after relevant declarations it will need */
-#include "asterisk/channel.h"
-#include "asterisk/utils.h"
+/*! \brief The global options available for CDRs */
+struct ast_cdr_config {
+ struct ast_flags settings; /*< CDR settings */
+ struct batch_settings {
+ unsigned int time; /*< Time between batches */
+ unsigned int size; /*< Size to trigger a batch */
+ struct ast_flags settings; /*< Settings for batches */
+ } batch_settings;
+};
/*!
* \brief Responsible for call detail data
@@ -133,249 +311,186 @@ struct ast_cdr {
struct ast_cdr *next;
};
-int ast_cdr_isset_unanswered(void);
-int ast_cdr_isset_congestion(void);
-void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw);
-int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur);
-int ast_cdr_serialize_variables(struct ast_cdr *cdr, struct ast_str **buf, char delim, char sep, int recur);
-void ast_cdr_free_vars(struct ast_cdr *cdr, int recur);
-int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr);
-
-/*!
- * \brief CDR backend callback
- * \warning CDR backends should NOT attempt to access the channel associated
- * with a CDR record. This channel is not guaranteed to exist when the CDR
- * backend is invoked.
- */
-typedef int (*ast_cdrbe)(struct ast_cdr *cdr);
-
-/*! \brief Return TRUE if CDR subsystem is enabled */
-int check_cdr_enabled(void);
-
/*!
- * \brief Allocate a CDR record
- * \retval a malloc'd ast_cdr structure
- * \retval NULL on error (malloc failure)
- */
-struct ast_cdr *ast_cdr_alloc(void);
-
-/*!
- * \brief Duplicate a record and increment the sequence number.
- * \param cdr the record to duplicate
- * \retval a malloc'd ast_cdr structure,
- * \retval NULL on error (malloc failure)
- * \see ast_cdr_dup()
- * \see ast_cdr_dup_unique_swap()
- */
-struct ast_cdr *ast_cdr_dup_unique(struct ast_cdr *cdr);
-
-/*!
- * \brief Duplicate a record and increment the sequence number of the old
- * record.
- * \param cdr the record to duplicate
- * \retval a malloc'd ast_cdr structure,
- * \retval NULL on error (malloc failure)
- * \note This version increments the original CDR's sequence number rather than
- * the duplicate's sequence number. The effect is as if the original CDR's
- * sequence number was swapped with the duplicate's sequence number.
+ * \since 12
+ * \brief Obtain the current CDR configuration
*
- * \see ast_cdr_dup()
- * \see ast_cdr_dup_unique()
- */
-struct ast_cdr *ast_cdr_dup_unique_swap(struct ast_cdr *cdr);
-
-/*!
- * \brief Duplicate a record
- * \param cdr the record to duplicate
- * \retval a malloc'd ast_cdr structure,
- * \retval NULL on error (malloc failure)
- * \see ast_cdr_dup_unique()
- * \see ast_cdr_dup_unique_swap()
- */
-struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr);
-
-/*!
- * \brief Free a CDR record
- * \param cdr ast_cdr structure to free
- * Returns nothing
- */
-void ast_cdr_free(struct ast_cdr *cdr);
-
-/*!
- * \brief Discard and free a CDR record
- * \param cdr ast_cdr structure to free
- * Returns nothing -- same as free, but no checks or complaints
+ * The configuration is a ref counted object. The caller of this function must
+ * decrement the ref count when finished with the configuration.
+ *
+ * \retval NULL on error
+ * \retval The current CDR configuration
*/
-void ast_cdr_discard(struct ast_cdr *cdr);
+struct ast_cdr_config *ast_cdr_get_config(void);
/*!
- * \brief Initialize based on a channel
- * \param cdr Call Detail Record to use for channel
- * \param chan Channel to bind CDR with
- * Initializes a CDR and associates it with a particular channel
- * \note The channel should be locked before calling.
- * \return 0 by default
+ * \since 12
+ * \brief Set the current CDR configuration
+ *
+ * \param config The new CDR configuration
*/
-int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan);
+void ast_cdr_set_config(struct ast_cdr_config *config);
/*!
- * \brief Initialize based on a channel
- * \param cdr Call Detail Record to use for channel
- * \param chan Channel to bind CDR with
- * Initializes a CDR and associates it with a particular channel
- * \note The channel should be locked before calling.
- * \return 0 by default
+ * \since 12
+ * \brief Format a CDR variable from an already posted CDR
+ *
+ * \param cdr The dispatched CDR to process
+ * \param name The name of the variable
+ * \param ret Pointer to the formatted buffer
+ * \param workspace A pointer to the buffer to use to format the variable
+ * \param workspacelen The size of \ref workspace
+ * \param raw If non-zero and a date/time is extraced, provide epoch seconds. Otherwise format as a date/time stamp
*/
-int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *chan);
+void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw);
/*!
- * \brief Register a CDR handling engine
- * \param name name associated with the particular CDR handler
- * \param desc description of the CDR handler
- * \param be function pointer to a CDR handler
- * Used to register a Call Detail Record handler.
- * \retval 0 on success.
- * \retval -1 on error
+ * \since 12
+ * \brief Retrieve a CDR variable from a channel's current CDR
+ *
+ * \param channel_name The name of the party A channel that the CDR is associated with
+ * \param name The name of the variable to retrieve
+ * \param value Buffer to hold the value
+ * \param length The size of the buffer
+ *
+ * \retval 0 on success
+ * \retval non-zero on failure
*/
-int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be);
+int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length);
/*!
- * \brief Unregister a CDR handling engine
- * \param name name of CDR handler to unregister
- * Unregisters a CDR by it's name
+ * \since 12
+ * \brief Set a variable on a CDR
+ *
+ * \param channel_name The channel to set the variable on
+ * \param name The name of the variable to set
+ * \param value The value of the variable to set
+ *
+ * \retval 0 on success
+ * \retval non-zero on failure
*/
-void ast_cdr_unregister(const char *name);
+int ast_cdr_setvar(const char *channel_name, const char *name, const char *value);
/*!
- * \brief Start a call
- * \param cdr the cdr you wish to associate with the call
- * Starts all CDR stuff necessary for monitoring a call
- * Returns nothing
- */
-void ast_cdr_start(struct ast_cdr *cdr);
-
-/*! \brief Answer a call
- * \param cdr the cdr you wish to associate with the call
- * Starts all CDR stuff necessary for doing CDR when answering a call
- * \note NULL argument is just fine.
+ * \since 12
+ * \brief Fork a CDR
+ *
+ * \param channel_name The name of the channel whose CDR should be forked
+ * \param options Options to control how the fork occurs.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
*/
-void ast_cdr_answer(struct ast_cdr *cdr);
+int ast_cdr_fork(const char *channel_name, struct ast_flags *options);
/*!
- * \brief A call wasn't answered
- * \param cdr the cdr you wish to associate with the call
- * Marks the channel disposition as "NO ANSWER"
- * Will skip CDR's in chain with ANS_LOCK bit set. (see
- * forkCDR() application.
+ * \since 12
+ * \brief Set a property on a CDR for a channel
+ *
+ * This function sets specific administrative properties on a CDR for a channel.
+ * This includes properties like preventing a CDR from being dispatched, to
+ * setting the channel as the preferred Party A in future CDRs. See
+ * \ref enum ast_cdr_options for more information.
+ *
+ * \param channel_name The CDR's channel
+ * \param option Option to apply to the CDR
+ *
+ * \retval 0 on success
+ * \retval 1 on error
*/
-extern void ast_cdr_noanswer(struct ast_cdr *cdr);
+int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option);
/*!
- * \brief A call was set to congestion
- * \param cdr the cdr you wish to associate with the call
- * Markst he channel disposition as "CONGESTION"
- * Will skip CDR's in chain with ANS_LOCK bit set. (see
- * forkCDR() application
+ * \since 12
+ * \brief Clear a property on a CDR for a channel
+ *
+ * Clears a flag previously set by \ref ast_cdr_set_property
+ *
+ * \param channel_name The CDR's channel
+ * \param option Option to clear from the CDR
+ *
+ * \retval 0 on success
+ * \retval 1 on error
*/
-extern void ast_cdr_congestion(struct ast_cdr *cdr);
+int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option);
/*!
- * \brief Busy a call
- * \param cdr the cdr you wish to associate with the call
- * Marks the channel disposition as "BUSY"
- * Will skip CDR's in chain with ANS_LOCK bit set. (see
- * forkCDR() application.
- * Returns nothing
+ * \brief Reset the detail record
+ * \param channel_name The channel that the CDR is associated with
+ * \param options Options that control what the reset operation does.
+ *
+ * Valid options are:
+ * \ref AST_CDR_FLAG_KEEP_VARS - keep the variables during the reset
+ * \ref AST_CDR_FLAG_DISABLE_ALL - when used with \ref ast_cdr_reset, re-enables
+ * the CDR
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
*/
-void ast_cdr_busy(struct ast_cdr *cdr);
+int ast_cdr_reset(const char *channel_name, struct ast_flags *options);
/*!
- * \brief Fail a call
- * \param cdr the cdr you wish to associate with the call
- * Marks the channel disposition as "FAILED"
- * Will skip CDR's in chain with ANS_LOCK bit set. (see
- * forkCDR() application.
- * Returns nothing
+ * \brief Serializes all the data and variables for a current CDR record
+ * \param channel_name The channel to get the CDR for
+ * \param buf A buffer to use for formatting the data
+ * \param delim A delimeter to use to separate variable keys/values
+ * \param sep A separator to use between nestings
+ * \retval the total number of serialized variables
*/
-void ast_cdr_failed(struct ast_cdr *cdr);
+int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep);
/*!
- * \brief Save the result of the call based on the AST_CAUSE_*
- * \param cdr the cdr you wish to associate with the call
- * \param cause the AST_CAUSE_*
- * Returns nothing
+ * \brief CDR backend callback
+ * \warning CDR backends should NOT attempt to access the channel associated
+ * with a CDR record. This channel is not guaranteed to exist when the CDR
+ * backend is invoked.
*/
-int ast_cdr_disposition(struct ast_cdr *cdr, int cause);
+typedef int (*ast_cdrbe)(struct ast_cdr *cdr);
-/*!
- * \brief End a call
- * \param cdr the cdr you have associated the call with
- * Registers the end of call time in the cdr structure.
- * Returns nothing
- */
-void ast_cdr_end(struct ast_cdr *cdr);
+/*! \brief Return TRUE if CDR subsystem is enabled */
+int ast_cdr_is_enabled(void);
/*!
- * \brief Detaches the detail record for posting (and freeing) either now or at a
- * later time in bulk with other records during batch mode operation.
- * \param cdr Which CDR to detach from the channel thread
- * Prevents the channel thread from blocking on the CDR handling
- * Returns nothing
+ * \brief Allocate a CDR record
+ * \retval a malloc'd ast_cdr structure
+ * \retval NULL on error (malloc failure)
*/
-void ast_cdr_detach(struct ast_cdr *cdr);
+struct ast_cdr *ast_cdr_alloc(void);
-/*!
- * \brief Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines
- * \param shutdown Whether or not we are shutting down
- * Blocks the asterisk shutdown procedures until the CDR data is submitted.
- * Returns nothing
- */
-void ast_cdr_submit_batch(int shutdown);
/*!
- * \brief Set the destination channel, if there was one
- * \param cdr Which cdr it's applied to
- * \param chan Channel to which dest will be
- * Sets the destination channel the CDR is applied to
- * Returns nothing
+ * \brief Duplicate a public CDR
+ * \param cdr the record to duplicate
+ *
+ * \retval a malloc'd ast_cdr structure,
+ * \retval NULL on error (malloc failure)
*/
-void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan);
+struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr);
/*!
- * \brief Set the last executed application
- * \param cdr which cdr to act upon
- * \param app the name of the app you wish to change it to
- * \param data the data you want in the data field of app you set it to
- * Changes the value of the last executed app
+ * \brief Free a CDR record
+ * \param cdr ast_cdr structure to free
* Returns nothing
*/
-void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data);
-
-/*!
- * \brief Set the answer time for a call
- * \param cdr the cdr you wish to associate with the call
- * \param t the answer time
- * Starts all CDR stuff necessary for doing CDR when answering a call
- * NULL argument is just fine.
- */
-void ast_cdr_setanswer(struct ast_cdr *cdr, struct timeval t);
+void ast_cdr_free(struct ast_cdr *cdr);
/*!
- * \brief Set the disposition for a call
- * \param cdr the cdr you wish to associate with the call
- * \param disposition the new disposition
- * Set the disposition on a call.
- * NULL argument is just fine.
+ * \brief Register a CDR handling engine
+ * \param name name associated with the particular CDR handler
+ * \param desc description of the CDR handler
+ * \param be function pointer to a CDR handler
+ * Used to register a Call Detail Record handler.
+ * \retval 0 on success.
+ * \retval -1 on error
*/
-void ast_cdr_setdisposition(struct ast_cdr *cdr, long int disposition);
+int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be);
/*!
- * \brief Convert a string to a detail record AMA flag
- * \param flag string form of flag
- * Converts the string form of the flag to the binary form.
- * \return the binary form of the flag
+ * \brief Unregister a CDR handling engine
+ * \param name name of CDR handler to unregister
+ * Unregisters a CDR by it's name
*/
-int ast_cdr_amaflags2int(const char *flag);
+void ast_cdr_unregister(const char *name);
/*!
* \brief Disposition to a string
@@ -383,81 +498,15 @@ int ast_cdr_amaflags2int(const char *flag);
* Converts the binary form of a disposition to string form.
* \return a pointer to the string form
*/
-char *ast_cdr_disp2str(int disposition);
-
-/*!
- * \brief Reset the detail record, optionally posting it first
- * \param cdr which cdr to act upon
- * \param flags |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it
- * |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's
- */
-void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags);
-
-/*! Reset the detail record times, flags */
-/*!
- * \param cdr which cdr to act upon
- * \param flags |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it
- * |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's
- */
-void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *flags);
-
-/*! Flags to a string */
-/*!
- * \param flags binary flag
- * Converts binary flags to string flags
- * Returns string with flag name
- */
-char *ast_cdr_flags2str(int flags);
-
-/*!
- * \brief Move the non-null data from the "from" cdr to the "to" cdr
- * \param to the cdr to get the goodies
- * \param from the cdr to give the goodies
- */
-void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from);
-
-/*!
- * \brief Set account code, will generate AMI event
- * \note The channel should be locked before calling.
- */
-int ast_cdr_setaccount(struct ast_channel *chan, const char *account);
-
-/*!
- * \brief Set the peer account
- * \note The channel should be locked before calling.
- */
-int ast_cdr_setpeeraccount(struct ast_channel *chan, const char *account);
-
-/*!
- * \brief Set AMA flags for channel
- * \note The channel should be locked before calling.
- */
-int ast_cdr_setamaflags(struct ast_channel *chan, const char *amaflags);
+const char *ast_cdr_disp2str(int disposition);
/*!
* \brief Set CDR user field for channel (stored in CDR)
- * \note The channel should be locked before calling.
- */
-int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield);
-/*!
- * \brief Append to CDR user field for channel (stored in CDR)
- * \note The channel should be locked before calling.
- */
-int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield);
-
-
-/*!
- * \brief Update CDR on a channel
- * \note The channel should be locked before calling.
+ *
+ * \param channel_name The name of the channel that owns the CDR
+ * \param userfield The user field to set
*/
-int ast_cdr_update(struct ast_channel *chan);
-
-
-extern int ast_default_amaflags;
-
-extern char ast_default_accountcode[AST_MAX_ACCOUNT_CODE];
-
-struct ast_cdr *ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr);
+void ast_cdr_setuserfield(const char *channel_name, const char *userfield);
/*! \brief Reload the configuration file cdr.conf and start/stop CDR scheduling thread */
int ast_cdr_engine_reload(void);
@@ -468,14 +517,4 @@ int ast_cdr_engine_init(void);
/*! Submit any remaining CDRs and prepare for shutdown */
void ast_cdr_engine_term(void);
-/*!
- * \brief
- * \param[in] tree Where to insert the cdr.
- * \param[in] cdr The cdr structure to insert in 'tree'.
- * \param[in] recur Go throw all the cdr levels.
- * \retval <0 on error.
- * \retval 0 on success.
- */
-int ast_cdr_data_add_structure(struct ast_data *tree, struct ast_cdr *cdr, int recur);
-
#endif /* _ASTERISK_CDR_H */
diff --git a/include/asterisk/cel.h b/include/asterisk/cel.h
index 034a96ab9..914037d4c 100644
--- a/include/asterisk/cel.h
+++ b/include/asterisk/cel.h
@@ -36,20 +36,6 @@ extern "C" {
#include "asterisk/event.h"
/*!
- * \brief AMA Flags
- *
- * \note This must much up with the AST_CDR_* defines for AMA flags.
- */
-enum ast_cel_ama_flag {
- AST_CEL_AMA_FLAG_NONE,
- AST_CEL_AMA_FLAG_OMIT,
- AST_CEL_AMA_FLAG_BILLING,
- AST_CEL_AMA_FLAG_DOCUMENTATION,
- /*! \brief Must be final entry */
- AST_CEL_AMA_FLAG_TOTAL,
-};
-
-/*!
* \brief CEL event types
*/
enum ast_cel_event_type {
@@ -162,17 +148,6 @@ const char *ast_cel_get_type_name(enum ast_cel_event_type type);
*/
enum ast_cel_event_type ast_cel_str_to_event_type(const char *name);
-/*!
- * \brief Convert AMA flag to printable string
- *
- * \param[in] flag the flag to convert to a string
- *
- * \since 1.8
- *
- * \return the string representation of the flag
- */
-const char *ast_cel_get_ama_flag_name(enum ast_cel_ama_flag flag);
-
/*!
* \brief Check and potentially retire a Linked ID
*
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 42d50f21b..1b36c14ae 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -131,11 +131,13 @@ References:
extern "C" {
#endif
-#define AST_MAX_EXTENSION 80 /*!< Max length of an extension */
-#define AST_MAX_CONTEXT 80 /*!< Max length of a context */
-#define AST_CHANNEL_NAME 80 /*!< Max length of an ast_channel name */
-#define MAX_LANGUAGE 40 /*!< Max length of the language setting */
-#define MAX_MUSICCLASS 80 /*!< Max length of the music class setting */
+#define AST_MAX_EXTENSION 80 /*!< Max length of an extension */
+#define AST_MAX_CONTEXT 80 /*!< Max length of a context */
+#define AST_MAX_ACCOUNT_CODE 20 /*!< Max length of an account code */
+#define AST_CHANNEL_NAME 80 /*!< Max length of an ast_channel name */
+#define MAX_LANGUAGE 40 /*!< Max length of the language setting */
+#define MAX_MUSICCLASS 80 /*!< Max length of the music class setting */
+#define AST_MAX_USER_FIELD 256 /*!< Max length of the channel user field */
#include "asterisk/frame.h"
#include "asterisk/chanvars.h"
@@ -915,6 +917,10 @@ enum {
* to continue.
*/
AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT = (1 << 22),
+ /*!
+ * This flag indicates that the channel was originated.
+ */
+ AST_FLAG_ORIGINATED = (1 << 23),
};
/*! \brief ast_bridge_config flags */
@@ -1028,6 +1034,16 @@ enum channelreloadreason {
};
/*!
+ * \brief Channel AMA Flags
+ */
+enum ama_flags {
+ AST_AMA_NONE = 0,
+ AST_AMA_OMIT,
+ AST_AMA_BILLING,
+ AST_AMA_DOCUMENTATION,
+};
+
+/*!
* \note None of the datastore API calls lock the ast_channel they are using.
* So, the channel should be locked before calling the functions that
* take a channel argument.
@@ -1100,7 +1116,7 @@ struct ast_channel * attribute_malloc __attribute__((format(printf, 13, 14)))
__ast_channel_alloc(int needqueue, int state, const char *cid_num,
const char *cid_name, const char *acctcode,
const char *exten, const char *context,
- const char *linkedid, const int amaflag,
+ const char *linkedid, enum ama_flags amaflag,
const char *file, int line, const char *function,
const char *name_fmt, ...);
@@ -1591,7 +1607,6 @@ int ast_answer(struct ast_channel *chan);
* \brief Answer a channel
*
* \param chan channel to answer
- * \param cdr_answer flag to control whether any associated CDR should be marked as 'answered'
*
* This function answers a channel and handles all necessary call
* setup functions.
@@ -1607,14 +1622,13 @@ int ast_answer(struct ast_channel *chan);
* \retval 0 on success
* \retval non-zero on failure
*/
-int ast_raw_answer(struct ast_channel *chan, int cdr_answer);
+int ast_raw_answer(struct ast_channel *chan);
/*!
* \brief Answer a channel, with a selectable delay before returning
*
* \param chan channel to answer
* \param delay maximum amount of time to wait for incoming media
- * \param cdr_answer flag to control whether any associated CDR should be marked as 'answered'
*
* This function answers a channel and handles all necessary call
* setup functions.
@@ -1630,7 +1644,7 @@ int ast_raw_answer(struct ast_channel *chan, int cdr_answer);
* \retval 0 on success
* \retval non-zero on failure
*/
-int __ast_answer(struct ast_channel *chan, unsigned int delay, int cdr_answer);
+int __ast_answer(struct ast_channel *chan, unsigned int delay);
/*!
* \brief Execute a Gosub call on the channel before a call is placed.
@@ -2197,6 +2211,28 @@ int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen,
void ast_deactivate_generator(struct ast_channel *chan);
/*!
+ * \since 12
+ * \brief Obtain how long the channel since the channel was created
+ *
+ * \param chan The channel object
+ *
+ * \retval 0 if the time value cannot be computed (or you called this really fast)
+ * \retval The number of seconds the channel has been up
+ */
+int ast_channel_get_duration(struct ast_channel *chan);
+
+/*!
+ * \since 12
+ * \brief Obtain how long it has been since the channel was answered
+ *
+ * \param chan The channel object
+ *
+ * \retval 0 if the channel isn't answered (or you called this really fast)
+ * \retval The number of seconds the channel has been up
+ */
+int ast_channel_get_up_time(struct ast_channel *chan);
+
+/*!
* \brief Set caller ID number, name and ANI and generate AMI event.
*
* \note Use ast_channel_set_caller() and ast_channel_set_caller_event() instead.
@@ -2728,12 +2764,6 @@ struct ast_channel *ast_channel_get_by_exten(const char *exten, const char *cont
/*! @} End channel search functions. */
/*!
- \brief propagate the linked id between chan and peer
- */
-void ast_channel_set_linkgroup(struct ast_channel *chan, struct ast_channel *peer);
-
-
-/*!
* \brief Initialize the given name structure.
* \since 1.8
*
@@ -3806,6 +3836,26 @@ void ast_channel_unlink(struct ast_channel *chan);
*/
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen);
+/*!
+ * \since 12
+ * \brief Convert a string to a detail record AMA flag
+ *
+ * \param flag string form of flag
+ *
+ * \retval the enum (integer) form of the flag
+ */
+enum ama_flags ast_channel_string2amaflag(const char *flag);
+
+/*!
+ * \since 12
+ * \brief Convert the enum representation of an AMA flag to a string representation
+ *
+ * \param flags integer flag
+ *
+ * \retval A string representation of the flag
+ */
+const char *ast_channel_amaflags2string(enum ama_flags flags);
+
/* ACCESSOR FUNTIONS */
/*! \brief Set the channel name */
void ast_channel_name_set(struct ast_channel *chan, const char *name);
@@ -3863,8 +3913,8 @@ char ast_channel_sending_dtmf_digit(const struct ast_channel *chan);
void ast_channel_sending_dtmf_digit_set(struct ast_channel *chan, char value);
struct timeval ast_channel_sending_dtmf_tv(const struct ast_channel *chan);
void ast_channel_sending_dtmf_tv_set(struct ast_channel *chan, struct timeval value);
-int ast_channel_amaflags(const struct ast_channel *chan);
-void ast_channel_amaflags_set(struct ast_channel *chan, int value);
+enum ama_flags ast_channel_amaflags(const struct ast_channel *chan);
+void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value);
int ast_channel_epfd(const struct ast_channel *chan);
void ast_channel_epfd_set(struct ast_channel *chan, int value);
int ast_channel_fdno(const struct ast_channel *chan);
@@ -3988,6 +4038,8 @@ void ast_channel_whentohangup_set(struct ast_channel *chan, struct timeval *valu
void ast_channel_varshead_set(struct ast_channel *chan, struct varshead *value);
struct timeval ast_channel_creationtime(struct ast_channel *chan);
void ast_channel_creationtime_set(struct ast_channel *chan, struct timeval *value);
+struct timeval ast_channel_answertime(struct ast_channel *chan);
+void ast_channel_answertime_set(struct ast_channel *chan, struct timeval *value);
/* List getters */
struct ast_hangup_handler_list *ast_channel_hangup_handlers(struct ast_channel *chan);
@@ -4278,4 +4330,27 @@ int ast_channel_move(struct ast_channel *dest, struct ast_channel *source);
*/
int ast_channel_forward_endpoint(struct ast_channel *chan, struct ast_endpoint *endpoint);
+/*!
+ * \brief Return the oldest linkedid between two channels.
+ *
+ * A channel linkedid is derived from the channel uniqueid which is formed like this:
+ * [systemname-]ctime.seq
+ *
+ * The systemname, and the dash are optional, followed by the epoch time followed by an
+ * integer sequence. Note that this is not a decimal number, since 1.2 is less than 1.11
+ * in uniqueid land.
+ *
+ * To compare two uniqueids, we parse out the integer values of the time and the sequence
+ * numbers and compare them, with time trumping sequence.
+ *
+ * \param a The linkedid value of the first channel to compare
+ * \param b The linkedid value of the second channel to compare
+ *
+ * \retval NULL on failure
+ * \retval The oldest linkedid value
+ * \since 12.0.0
+*/
+const char *ast_channel_oldest_linkedid(const char *a, const char *b);
+
+
#endif /* _ASTERISK_CHANNEL_H */
diff --git a/include/asterisk/channel_internal.h b/include/asterisk/channel_internal.h
index 38776c1e1..a54a1b848 100644
--- a/include/asterisk/channel_internal.h
+++ b/include/asterisk/channel_internal.h
@@ -18,8 +18,8 @@
* \brief Internal channel functions for channel.c to use
*/
-#define ast_channel_internal_alloc(destructor) __ast_channel_internal_alloc(destructor, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj), const char *file, int line, const char *function);
+#define ast_channel_internal_alloc(destructor, linkedid) __ast_channel_internal_alloc(destructor, linkedid, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj), const char *linkedid, const char *file, int line, const char *function);
void ast_channel_internal_finalize(struct ast_channel *chan);
int ast_channel_internal_is_finalized(struct ast_channel *chan);
void ast_channel_internal_cleanup(struct ast_channel *chan);
diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h
index 339c77274..ca075ae69 100644
--- a/include/asterisk/stasis_channels.h
+++ b/include/asterisk/stasis_channels.h
@@ -38,36 +38,38 @@
*/
struct ast_channel_snapshot {
AST_DECLARE_STRING_FIELDS(
- AST_STRING_FIELD(name); /*!< ASCII unique channel name */
- AST_STRING_FIELD(accountcode); /*!< Account code for billing */
- AST_STRING_FIELD(peeraccount); /*!< Peer account code for billing */
- AST_STRING_FIELD(userfield); /*!< Userfield for CEL billing */
- AST_STRING_FIELD(uniqueid); /*!< Unique Channel Identifier */
- AST_STRING_FIELD(linkedid); /*!< Linked Channel Identifier -- gets propagated by linkage */
- AST_STRING_FIELD(parkinglot); /*!< Default parking lot, if empty, default parking lot */
- AST_STRING_FIELD(hangupsource); /*!< Who is responsible for hanging up this channel */
- AST_STRING_FIELD(appl); /*!< Current application */
- AST_STRING_FIELD(data); /*!< Data passed to current application */
- AST_STRING_FIELD(context); /*!< Dialplan: Current extension context */
- AST_STRING_FIELD(exten); /*!< Dialplan: Current extension number */
- AST_STRING_FIELD(caller_name); /*!< Caller ID Name */
- AST_STRING_FIELD(caller_number); /*!< Caller ID Number */
- AST_STRING_FIELD(caller_ani); /*!< Caller ID ANI Number */
- AST_STRING_FIELD(caller_rdnis); /*!< Caller ID RDNIS Number */
- AST_STRING_FIELD(caller_dnid); /*!< Caller ID DNID Number */
- AST_STRING_FIELD(connected_name); /*!< Connected Line Name */
- AST_STRING_FIELD(connected_number); /*!< Connected Line Number */
- AST_STRING_FIELD(language); /*!< The default spoken language for the channel */
+ AST_STRING_FIELD(name); /*!< ASCII unique channel name */
+ AST_STRING_FIELD(accountcode); /*!< Account code for billing */
+ AST_STRING_FIELD(peeraccount); /*!< Peer account code for billing */
+ AST_STRING_FIELD(userfield); /*!< Userfield for CEL billing */
+ AST_STRING_FIELD(uniqueid); /*!< Unique Channel Identifier */
+ AST_STRING_FIELD(linkedid); /*!< Linked Channel Identifier -- gets propagated by linkage */
+ AST_STRING_FIELD(parkinglot); /*!< Default parking lot, if empty, default parking lot */
+ AST_STRING_FIELD(hangupsource); /*!< Who is responsible for hanging up this channel */
+ AST_STRING_FIELD(appl); /*!< Current application */
+ AST_STRING_FIELD(data); /*!< Data passed to current application */
+ AST_STRING_FIELD(context); /*!< Dialplan: Current extension context */
+ AST_STRING_FIELD(exten); /*!< Dialplan: Current extension number */
+ AST_STRING_FIELD(caller_name); /*!< Caller ID Name */
+ AST_STRING_FIELD(caller_number); /*!< Caller ID Number */
+ AST_STRING_FIELD(caller_dnid); /*!< Dialed ID Number */
+ AST_STRING_FIELD(caller_ani); /*< Caller ID ANI Number */
+ AST_STRING_FIELD(caller_rdnis); /*!< Caller ID RDNIS Number */
+ AST_STRING_FIELD(caller_subaddr); /*!< Caller subaddress */
+ AST_STRING_FIELD(dialed_subaddr); /*!< Dialed subaddress */
+ AST_STRING_FIELD(connected_name); /*!< Connected Line Name */
+ AST_STRING_FIELD(connected_number); /*!< Connected Line Number */
+ AST_STRING_FIELD(language); /*!< The default spoken language for the channel */
);
- struct timeval creationtime; /*!< The time of channel creation */
- enum ast_channel_state state; /*!< State of line */
- int priority; /*!< Dialplan: Current extension priority */
- int amaflags; /*!< AMA flags for billing */
- int hangupcause; /*!< Why is the channel hanged up. See causes.h */
- int caller_pres; /*!< Caller ID presentation. */
- struct ast_flags flags; /*!< channel flags of AST_FLAG_ type */
- struct varshead *manager_vars; /*!< Variables to be appended to manager events */
+ struct timeval creationtime; /*!< The time of channel creation */
+ enum ast_channel_state state; /*!< State of line */
+ int priority; /*!< Dialplan: Current extension priority */
+ int amaflags; /*!< AMA flags for billing */
+ int hangupcause; /*!< Why is the channel hanged up. See causes.h */
+ int caller_pres; /*!< Caller ID presentation. */
+ struct ast_flags flags; /*!< channel flags of AST_FLAG_ type */
+ struct varshead *manager_vars; /*!< Variables to be appended to manager events */
};
/*!
@@ -300,7 +302,7 @@ void ast_channel_publish_snapshot(struct ast_channel *chan);
* \since 12
* \brief Publish a \ref ast_channel_varset for a channel.
*
- * \param chan Channel to pulish the event for, or \c NULL for 'none'.
+ * \param chan Channel to publish the event for, or \c NULL for 'none'.
* \param variable Name of the variable being set
* \param value Value.
*/
diff --git a/include/asterisk/stasis_internal.h b/include/asterisk/stasis_internal.h
new file mode 100644
index 000000000..67ab88ff0
--- /dev/null
+++ b/include/asterisk/stasis_internal.h
@@ -0,0 +1,69 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * Matt Jordan <mjordan@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.
+ */
+
+#ifndef STASIS_INTERNAL_H_
+#define STASIS_INTERNAL_H_
+
+/*! \file
+ *
+ * \brief Internal Stasis APIs.
+ *
+ * This header file is used to define functions that are shared between files that make
+ * up \ref stasis. Functions declared here should not be used by any module outside of
+ * Stasis.
+ *
+ * If you find yourself needing to call one of these functions directly, something has
+ * probably gone horribly wrong.
+ *
+ * \author Matt Jordan <mjordan@digium.com>
+ */
+
+struct stasis_topic;
+struct stasis_subscription;
+struct stasis_message;
+
+/*!
+ * \brief Create a subscription.
+ *
+ * In addition to being AO2 managed memory (requiring an ao2_cleanup() to free
+ * up this reference), the subscription must be explicitly unsubscribed from its
+ * topic using stasis_unsubscribe().
+ *
+ * The invocations of the callback are serialized, but may not always occur on
+ * the same thread. The invocation order of different subscriptions is
+ * unspecified.
+ *
+ * Note: modules outside of Stasis should use \ref stasis_subscribe.
+ *
+ * \param topic Topic to subscribe to.
+ * \param callback Callback function for subscription messages.
+ * \param data Data to be passed to the callback, in addition to the message.
+ * \param needs_mailbox Determines whether or not the subscription requires a mailbox.
+ * Subscriptions with mailboxes will be delivered on a thread in the Stasis threadpool;
+ * subscriptions without mailboxes will be delivered on the publisher thread.
+ * \return New \ref stasis_subscription object.
+ * \return \c NULL on error.
+ * \since 12
+ */
+struct stasis_subscription *internal_stasis_subscribe(
+ struct stasis_topic *topic,
+ void (*stasis_subscription_cb)(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message),
+ void *data,
+ int needs_mailbox);
+
+#endif /* STASIS_INTERNAL_H_ */
diff --git a/include/asterisk/test.h b/include/asterisk/test.h
index d890b7a3e..d29969f8b 100644
--- a/include/asterisk/test.h
+++ b/include/asterisk/test.h
@@ -238,7 +238,9 @@ struct ast_test_info {
/*!
* \brief Generic test callback function
*
- * \param error buffer string for failure results
+ * \param info The test info object
+ * \param cmd What to perform in the test
+ * \param test The actual test object being manipulated
*
* \retval AST_TEST_PASS for pass
* \retval AST_TEST_FAIL for failure
@@ -247,6 +249,30 @@ typedef enum ast_test_result_state (ast_test_cb_t)(struct ast_test_info *info,
enum ast_test_command cmd, struct ast_test *test);
/*!
+ * \since 12
+ * \brief A test initialization callback function
+ *
+ * \param info The test info object
+ * \param test The actual test object that will be manipulated
+ *
+ * \retval 0 success
+ * \retval other failure. This will fail the test.
+ */
+typedef int (ast_test_init_cb_t)(struct ast_test_info *info, struct ast_test *test);
+
+/*!
+ * \since 12
+ * \brief A test cleanup callback function
+ *
+ * \param info The test info object
+ * \param test The actual test object that was executed
+ *
+ * \retval 0 success
+ * \retval other failure. This will fail the test.
+ */
+typedef int (ast_test_cleanup_cb_t)(struct ast_test_info *info, struct ast_test *test);
+
+/*!
* \brief unregisters a test with the test framework
*
* \param test callback function (required)
@@ -267,6 +293,40 @@ int ast_test_unregister(ast_test_cb_t *cb);
int ast_test_register(ast_test_cb_t *cb);
/*!
+ * \since 12
+ * \brief Register an initialization function to be run before each test
+ * executes
+ *
+ * This function lets a registered test have an initialization function that
+ * will be run prior to test execution. Each category may have a single init
+ * function.
+ *
+ * If the initialization function returns a non-zero value, the test will not
+ * be executed and the result will be set to \ref AST_TEST_FAIL.
+ *
+ * \retval 0 success
+ * \retval other failure
+ */
+int ast_test_register_init(const char *category, ast_test_init_cb_t *cb);
+
+/*!
+ * \since 12
+ * \brief Register a cleanup function to be run after each test executes
+ *
+ * This function lets a registered test have a cleanup function that will be
+ * run immediately after test execution. Each category may have a single
+ * cleanup function.
+ *
+ * If the cleanup function returns a non-zero value, the test result will be
+ * set to \ref AST_TEST_FAIL.
+ *
+ * \retval 0 success
+ * \retval other failure
+ */
+int ast_test_register_cleanup(const char *category, ast_test_cleanup_cb_t *cb);
+
+
+/*!
* \brief Unit test debug output.
* \since 12.0.0
*
@@ -278,6 +338,17 @@ int ast_test_register(ast_test_cb_t *cb);
void ast_test_debug(struct ast_test *test, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
/*!
+ * \brief Set the result of a test.
+ *
+ * If the caller of this function sets the result to AST_TEST_FAIL, returning
+ * AST_TEST_PASS from the test will not pass the test. This lets a test writer
+ * end and fail a test and continue on with logic, catching multiple failure
+ * conditions within a single test.
+ */
+void ast_test_set_result(struct ast_test *test, enum ast_test_result_state state);
+
+
+/*!
* \brief update test's status during testing.
*
* \param test currently executing test
diff --git a/include/asterisk/time.h b/include/asterisk/time.h
index dd68db704..f2382df33 100644
--- a/include/asterisk/time.h
+++ b/include/asterisk/time.h
@@ -152,6 +152,17 @@ struct timeval ast_tvadd(struct timeval a, struct timeval b);
struct timeval ast_tvsub(struct timeval a, struct timeval b);
/*!
+ * \since 12
+ * \brief Formats a duration into HH:MM:SS
+ *
+ * \param duration The time (in seconds) to format
+ * \param buf A buffer to hold the formatted string'
+ * \param length The size of the buffer
+ */
+void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length);
+
+
+/*!
* \brief Calculate remaining milliseconds given a starting timestamp
* and upper bound
*