123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- /*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@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 Detail Record API
- *
- * \author Mark Spencer <markster@digium.com>
- */
- #ifndef _ASTERISK_CDR_H
- #define _ASTERISK_CDR_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
- * \li If a \ref ast_bridge_blob_type message indicating an entrance to a
- * holding bridge with a subclass type of "parking" is received, the CDR is
- * transitioned to the Parked state.
- *
- * \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)
- * \li If a \ref ast_bridge_blob_type message indicating an entrance to a
- * holding bridge with a subclass type of "parking" is received, the CDR is
- * transitioned to the Parked 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 Finalized state.
- *
- * \par Parked
- *
- * Parking is technically just another bridge in the Asterisk bridging
- * framework. Unlike other bridges, however there are several key distinctions:
- * \li With normal bridges, you want to show paths of communication between
- * the participants. In parking, however, each participant is independent.
- * From the perspective of a CDR, a call in parking should look like a dialplan
- * application just executed.
- * \li Holding bridges are typically items using in more complex applications,
- * and so we usually don't want to show them. However, with Park, there is no
- * application execution - often, a channel will be put directly into the
- * holding bridge, bypassing the dialplan. This occurs when a call is blind
- * transferred to a parking extension.
- *
- * As such, if a channel enters a bridge and that happens to be a holding bridge
- * with a subclass type of "parking", we transition the CDR into the Parked
- * state. The parking Stasis message updates the application name and data to
- * reflect that the channel is in parking. When this occurs, a special flag is
- * set on the CDR that prevents the application name from being updates by
- * subsequent channel snapshot updates.
- *
- * The following transitions can occur while in the Parked state:
- * \li If a \ref ast_bridge_blob_type message indicating a leave is received,
- * the state transitions 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 */
- };
- /*! \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 manipulation options. Certain function calls will manipulate the
- * state of a CDR object based on these flags.
- */
- 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 */
- AST_CDR_LOCK_APP = (1 << 7), /*!< Prevent any further changes to the application field/data field for this CDR */
- };
- /*!
- * \brief CDR Flags - Disposition
- */
- enum ast_cdr_disposition {
- AST_CDR_NOANSWER = 0,
- AST_CDR_NULL = (1 << 0),
- AST_CDR_FAILED = (1 << 1),
- AST_CDR_BUSY = (1 << 2),
- AST_CDR_ANSWERED = (1 << 3),
- AST_CDR_CONGESTION = (1 << 4),
- };
- /*! \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
- */
- struct ast_cdr {
- /*! Caller*ID with text */
- char clid[AST_MAX_EXTENSION];
- /*! Caller*ID number */
- char src[AST_MAX_EXTENSION];
- /*! Destination extension */
- char dst[AST_MAX_EXTENSION];
- /*! Destination context */
- char dcontext[AST_MAX_EXTENSION];
- char channel[AST_MAX_EXTENSION];
- /*! Destination channel if appropriate */
- char dstchannel[AST_MAX_EXTENSION];
- /*! Last application if appropriate */
- char lastapp[AST_MAX_EXTENSION];
- /*! Last application data */
- char lastdata[AST_MAX_EXTENSION];
- struct timeval start;
- struct timeval answer;
- struct timeval end;
- /*! Total time in system, in seconds */
- long int duration;
- /*! Total time call is up, in seconds */
- long int billsec;
- /*! What happened to the call */
- long int disposition;
- /*! What flags to use */
- long int amaflags;
- /*! What account number to use */
- char accountcode[AST_MAX_ACCOUNT_CODE];
- /*! Account number of the last person we talked to */
- char peeraccount[AST_MAX_ACCOUNT_CODE];
- /*! flags */
- unsigned int flags;
- /*! Unique Channel Identifier */
- char uniqueid[AST_MAX_UNIQUEID];
- /*! Linked group Identifier */
- char linkedid[AST_MAX_UNIQUEID];
- /*! User field */
- char userfield[AST_MAX_USER_FIELD];
- /*! Sequence field */
- int sequence;
- /*! A linked list for variables */
- struct varshead varshead;
- struct ast_cdr *next;
- };
- /*!
- * \since 12
- * \brief Obtain the current CDR configuration
- *
- * 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
- */
- struct ast_cdr_config *ast_cdr_get_config(void);
- /*!
- * \since 12
- * \brief Set the current CDR configuration
- *
- * \param config The new CDR configuration
- */
- void ast_cdr_set_config(struct ast_cdr_config *config);
- /*!
- * \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
- */
- void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw);
- /*!
- * \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_getvar(const char *channel_name, const char *name, char *value, size_t length);
- /*!
- * \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
- */
- int ast_cdr_setvar(const char *channel_name, const char *name, const char *value);
- /*!
- * \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
- */
- int ast_cdr_fork(const char *channel_name, struct ast_flags *options);
- /*!
- * \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
- */
- int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option);
- /*!
- * \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
- */
- int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option);
- /*!
- * \brief Reset the detail record
- * \param channel_name The channel that the CDR is associated with
- * \param keep_variables Keep the variables during the reset. If zero,
- * variables are discarded during the reset.
- *
- * \retval 0 on success
- * \retval -1 on failure
- */
- int ast_cdr_reset(const char *channel_name, int keep_variables);
- /*!
- * \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
- */
- int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep);
- /*!
- * \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 ast_cdr_is_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);
- struct stasis_message_router;
- /*!
- * \brief Return the message router for the CDR engine
- *
- * This returns the \ref stasis_message_router that the CDR engine
- * uses for dispatching \ref stasis messages. The reference on the
- * message router is bumped and must be released by the caller of
- * this function.
- *
- * \retval NULL if the CDR engine is disabled or unavailable
- * \retval the \ref stasis_message_router otherwise
- */
- struct stasis_message_router *ast_cdr_message_router(void);
- /*!
- * \brief Duplicate a public CDR
- * \param cdr the record to duplicate
- *
- * \retval a malloc'd ast_cdr structure,
- * \retval NULL on error (malloc failure)
- */
- 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 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
- */
- int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be);
- /*!
- * \brief Unregister a CDR handling engine
- * \param name name of CDR handler to unregister
- * Unregisters a CDR by it's name
- *
- * \retval 0 The backend unregistered successfully
- * \retval -1 The backend could not be unregistered at this time
- */
- int ast_cdr_unregister(const char *name);
- /*!
- * \brief Suspend a CDR backend temporarily
- *
- * \retval 0 The backend is suspdended
- * \retval -1 The backend could not be suspended
- */
- int ast_cdr_backend_suspend(const char *name);
- /*!
- * \brief Unsuspend a CDR backend
- *
- * \retval 0 The backend was unsuspended
- * \retval -1 The back could not be unsuspended
- */
- int ast_cdr_backend_unsuspend(const char *name);
- /*!
- * \brief Disposition to a string
- * \param disposition input binary form
- * Converts the binary form of a disposition to string form.
- * \return a pointer to the string form
- */
- const char *ast_cdr_disp2str(int disposition);
- /*!
- * \brief Set CDR user field for channel (stored in CDR)
- *
- * \param channel_name The name of the channel that owns the CDR
- * \param userfield The user field to set
- */
- 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);
- /*! \brief Load the configuration file cdr.conf and possibly start the CDR scheduling thread */
- int ast_cdr_engine_init(void);
- /*! Submit any remaining CDRs and prepare for shutdown */
- void ast_cdr_engine_term(void);
- #endif /* _ASTERISK_CDR_H */
|