framehook.h

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2010, Digium, Inc.
00005  *
00006  * David Vossel <dvossel@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  * \brief FrameHook Architecture
00021  */
00022 
00023 /*!
00024 
00025 \page AstFrameHookAPI Asterisk FrameHook API
00026 
00027 \section FrameHookFunctionality How FrameHooks Work
00028    FrameHooks work by intercepting all frames being written and read off
00029    a channel and allowing those frames to be viewed and manipulated within a
00030    call back function.  Frame interception occurs before any processing is
00031    done on the frame, which means this hook can be used to transparently
00032    manipulate a frame before it is read from the channel or written
00033    to the tech_pvt.  This API can be thought of as a layer between the
00034    channel API and the Asterisk core when going in the READ direction, and
00035    as a layer between the Channel API and the tech_pvt when going in the
00036    WRITE direction.
00037 
00038 \section FrameHookAPIUsage How to Use an FrameHook
00039    Attaching and detaching an FrameHook to a channel is very simple.  There are only
00040    two functions involved, ast_framehook_attach() which will return an id representing
00041    the new FrameHook on the channel, and ast_framehook_detach() which signals the
00042    FrameHook for detachment and destruction. Below is detailed information each of these
00043    functions and their usage.
00044 
00045 \code
00046    struct ast_framehook_interface interface = {
00047       .version = AST_FRAMEHOOK_INTERFACE_VERSION,
00048       .event_cb = hook_event_cb,
00049       .destroy_cb = hook_destroy_cb,
00050       .data = data, // where the data ptr points to any custom data used later by the hook cb.
00051    };
00052    int id = ast_framehook_attach(channel, &interface);
00053 \endcode
00054 
00055    The ast_framehook_attach() function creates and attaches a new FrameHook onto
00056    a channel. Once attached to the channel, the FrameHook will call the event_callback
00057    function each time a frame is written or read on the channel.  A custom data
00058    pointer can be provided to this function to store on the FrameHook as well.  This
00059    pointer can be used to keep up with any statefull information associated with the FrameHook
00060    and is provided during the event_callback function.  The destroy_callback function is optional.
00061    This function exists so any custom data stored on the FrameHook can be destroyed before
00062    the Framehook if destroyed.
00063 
00064 \code
00065    ast_framehook_detach(channel, id);
00066 \endcode
00067 
00068    The ast_framehook_detach() function signals the FrameHook represented by an id to
00069    be detached and destroyed on a channel.  Since it is possible this function may be called
00070    during the FrameHook's event callback, it is impossible to synchronously detach the
00071    FrameHook from the channel during this function call.  It is guaranteed that the next
00072    event proceeding the ast_framehook_detach() will be of type AST_FRAMEHOOK_EVENT_DETACH,
00073    and that after that event occurs no other event will ever be issued for that FrameHook.
00074    Once the FrameHook is destroyed, the destroy callback function will be called if it was
00075    provided. Note that if this function is never called, the FrameHook will be detached
00076    on channel destruction.
00077 
00078 \section FrameHookAPICodeExample FrameHook Example Code
00079    The example code below attaches an FrameHook on a channel, and then detachs it when
00080    the first ast_frame is read or written to the event callback function.  The Framehook's id
00081    is stored on the FrameHook's data pointer so it can be detached within the callback.
00082 
00083 \code
00084    static void destroy_cb(void *data) {
00085       ast_free(data);
00086    }
00087 
00088    static struct ast_frame *event_cb(struct ast_channel *chan,
00089          struct ast_frame *frame,
00090          enum ast_framehook_event event,
00091          void *data) {
00092 
00093       int *id = data;
00094 
00095       if (!frame) {
00096          return frame;
00097       }
00098 
00099       if (event == AST_FRAMEHOOK_EVENT_WRITE) {
00100          ast_log(LOG_NOTICE, "YAY we received a frame in the write direction, Type: %d\n", frame->frametype)
00101          ast_framehook_detach(chan, id); // the channel is guaranteed to be locked during this function call.
00102       } else if (event == AST_FRAMEHOOK_EVENT_READ) {
00103          ast_log(LOG_NOTICE, "YAY we received a frame in the read direction: Type: %d\n", frame->frametype);
00104          ast_framehook_detach(chan, id); // the channel is guaranteed to be locked during this function call.
00105       }
00106 
00107       return frame;
00108    {
00109 
00110    int some_function()
00111    {
00112       struct ast_framehook_interface interface = {
00113          .version = AST_FRAMEHOOK_INTERFACE_VERSION,
00114          .event_cb = hook_event_cb,
00115          .destroy_cb = hook_destroy_cb,
00116       };
00117       int *id = ast_calloc(1, sizeof(int));
00118 
00119       if (!id) {
00120          return -1;
00121       }
00122 
00123       interface.data = id; // This data will be returned to us in the callbacks.
00124 
00125       ast_channel_lock(chan);
00126       *id = ast_framehook_attach(chan, &interface);
00127       ast_channel_unlock(chan);
00128 
00129       if (*id < 0) {
00130          // framehook attach failed, free data
00131          ast_free(id);
00132          return -1;
00133       }
00134       return 0;
00135    }
00136 \endcode
00137 */
00138 
00139 #ifndef _AST_FRAMEHOOK_H_
00140 #define _AST_FRAMEHOOK_H_
00141 #include "asterisk/linkedlists.h"
00142 #include "asterisk/frame.h"
00143 
00144 struct ast_framehook;
00145 struct ast_framehook_list;
00146 
00147 /*!
00148  * \brief These are the types of events that the framehook's event callback can receive
00149  * \since 1.8
00150  */
00151 enum ast_framehook_event {
00152    AST_FRAMEHOOK_EVENT_READ, /*!< frame is intercepted in the read direction on the channel. */
00153    AST_FRAMEHOOK_EVENT_WRITE, /*!< frame is intercepted on the write direction on the channel. */
00154    AST_FRAMEHOOK_EVENT_ATTACHED, /*!< framehook is attached and running on the channel, the first message sent to event_cb. */
00155    AST_FRAMEHOOK_EVENT_DETACHED /*!< framehook is detached from the channel, last message sent to event_cb. */
00156 };
00157 
00158 /*!
00159  * \brief This callback is called every time an event occurs on the framehook.
00160  * \since 1.8
00161  *
00162  * \details Two events are guaranteed to occur once the ast_framehook_attach()
00163  * function is called. These events are AST_FRAMEHOOK_EVENT_ATTACHED, which occurs
00164  * immediately after the framehook is attached to a channel, and
00165  * AST_FRAMEHOOK_EVENT_DETACHED, which occurs right after the framehook is 
00166  * detached.
00167  *
00168  * It is completely valid for the frame variable to be set to NULL. Always do a NULL
00169  * check on the frame before attempted to access it. When the frame variable is present,
00170  * it is safe to view and manipulate that frame in any way possible.  It is even safe
00171  * to return a completely different frame, but when that occurs this function is in
00172  * charge of freeing the previous frame.
00173  *
00174  * The ast_channel will always be locked during this callback. Never attempt to unlock the
00175  * channel for any reason.
00176  *
00177  * \param channel, The ast_channel this framehook is attached to
00178  * \param frame, The ast_frame being intercepted for viewing and manipulation
00179  * \param event, The type of event which is occurring
00180  * \param data, The data pointer provided at framehook initilization.
00181  *
00182  * \retval the resulting frame.
00183  */
00184 typedef struct ast_frame *(*ast_framehook_event_callback)(
00185    struct ast_channel *chan,
00186    struct ast_frame *frame,
00187    enum ast_framehook_event event,
00188    void *data);
00189 
00190 /*!
00191  * \brief This callback is called immediately before the framehook is destroyed.
00192  * \since 1.8
00193  * \note  This function should be used to clean up any pointers pointing to the
00194  * framehook structure as the framehook will be freed immediately afterwards.
00195  *
00196  * \param data, The data pointer provided at framehook initialization. This
00197  * is a good place to clean up any state data allocated for the framehook stored in this
00198  * pointer.
00199  */
00200 typedef void (*ast_framehook_destroy_callback)(void *data);
00201 
00202 /*!
00203  * \brief This callback is called to determine if the framehook is currently consuming
00204  * frames of a given type
00205  * \since 12
00206  *
00207  * \param data, The data pointer provided at framehook initilization.
00208  * \param type, The type of frame.
00209  *
00210  * \return 0 if frame type is being ignored
00211  * \return 1 if frame type is not being ignored
00212  */
00213 typedef int (*ast_framehook_consume_callback)(void *data, enum ast_frame_type type);
00214 
00215 /*!
00216  * \brief This callback is called when a masquerade occurs on a channel with a framehook
00217  * \since 12
00218  *
00219  * \param data, The data pointer provided at framehook initialization.
00220  * \param framehook_id, The framehook ID where the framehook lives now
00221  * \param old_chan, The channel that was masqueraded.
00222  * \param new_chan, The channel that the masqueraded channel became.
00223  */
00224 typedef void (*ast_framehook_chan_fixup_callback)(void *data, int framehook_id,
00225    struct ast_channel *old_chan, struct ast_channel *new_chan);
00226 
00227 #define AST_FRAMEHOOK_INTERFACE_VERSION 4
00228 /*! This interface is required for attaching a framehook to a channel. */
00229 struct ast_framehook_interface {
00230    /*! framehook interface version number */
00231    uint16_t version;
00232    /*! event_cb represents the function that will be called everytime an event occurs on the framehook. */
00233    ast_framehook_event_callback event_cb;
00234    /*! destroy_cb is optional.  This function is called immediately before the framehook
00235     * is destroyed to allow for stored_data cleanup. */
00236    ast_framehook_destroy_callback destroy_cb;
00237    /*! consume_cb is optional. This function is called to query whether the framehook is consuming
00238    * frames of a specific type at this time. If this callback is not implemented it is assumed that the
00239    * framehook will consume frames of all types. */
00240    ast_framehook_consume_callback consume_cb;
00241    /*! chan_fixup_cb is optional. This function is called when the channel that a framehook is running
00242     * on is masqueraded and should be used to move any essential framehook data onto the channel the
00243     * old channel was masqueraded to. */
00244    ast_framehook_chan_fixup_callback chan_fixup_cb;
00245    /*! chan_breakdown_cb is optional. This function is called when another channel is masqueraded into
00246     * the channel that a framehook is running on and should be used to evaluate whether the framehook
00247     * should remain on the channel. */
00248    ast_framehook_chan_fixup_callback chan_breakdown_cb;
00249    /*! disable_inheritance is optional. If set to non-zero, when a channel using this framehook is
00250     * masqueraded, detach and destroy the framehook instead of moving it to the new channel. */
00251    int disable_inheritance;
00252     /*! This pointer can represent any custom data to be stored on the !framehook. This
00253     * data pointer will be provided during each event callback which allows the framehook
00254     * to store any stateful data associated with the application using the hook. */
00255    void *data;
00256 };
00257 
00258 /*!
00259  * \brief Attach an framehook onto a channel for frame interception.
00260  * \since 1.8
00261  *
00262  * \param chan ast_channel The channel to attach the hook on to.
00263  * \param i framehook interface, The framehook's callback functions and stored data.
00264  *
00265  * \pre The Channel must be locked during this function call.
00266  *
00267  * \note The data pointer is never touched by the framehook API except to
00268  * provide it during the event and destruction callbacks.  It is entirely up to the
00269  * application using this API to manage the memory associated with the data pointer.
00270  *
00271  * \retval On success, non-negative id representing this hook on the channel
00272  * \retval On failure, -1
00273  */
00274 int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i);
00275 
00276 /*!
00277  * \brief Detach an framehook from a channel.
00278  * \since 1.8
00279  * 
00280  * \pre The Channel must be locked during this function call.
00281  * If this function is never called after attaching an framehook,
00282  * the framehook will be detached and destroyed during channel
00283  * destruction.
00284  *
00285  * \param chan The channel the framehook is attached to
00286  * \param framehook_id The framehook's id
00287  *
00288  * \retval 0 success
00289  * \retval -1 framehook did not exist on the channel. This means the
00290  * framehook either never existed on the channel, or was already detached.
00291  */
00292 int ast_framehook_detach(struct ast_channel *chan, int framehook_id);
00293 
00294 /*!
00295  * \brief This is used by the channel API to detach and destroy all
00296  * framehooks on a channel during channel destruction.
00297  * \since 1.8
00298  *
00299  * \pre The Channel must be locked during this function call.
00300  * 
00301  * \param chan channel containing the framehook list to destroy.
00302  * \retval 0 success
00303  * \retval -1 failure
00304  */
00305 int ast_framehook_list_destroy(struct ast_channel *chan);
00306 
00307 /*!
00308  * \brief This is used by the channel API during a masquerade operation
00309  * to move all mobile framehooks from the original channel to the clone channel.
00310  * \since 12.5.0
00311  *
00312  * \pre Both channels must be locked prior to this function call.
00313  *
00314  * \param old_chan The channel being cloned from
00315  * \param new_chan The channel being cloned to
00316  */
00317 void ast_framehook_list_fixup(struct ast_channel *old_chan, struct ast_channel *new_chan);
00318 
00319 /*!
00320  * \brief This is used by the channel API push a frame read event to a channel's framehook list.
00321  * \since 1.8
00322  *
00323  * \details After this function completes, the resulting frame that is returned could be anything,
00324  * even NULL.  There is nothing to keep up with after this function. If the frame is modified, the
00325  * framehook callback is in charge of any memory management associated with that modification.
00326  *
00327  * \pre The Channel must be locked during this function call.
00328  *
00329  * \param framehooks list to push event to.
00330  * \param frame being pushed to the framehook list.
00331  *
00332  * \return The resulting frame after being viewed and modified by the framehook callbacks.
00333  */
00334 struct ast_frame *ast_framehook_list_read_event(struct ast_framehook_list *framehooks, struct ast_frame *frame);
00335 
00336 /*!
00337  * \brief This is used by the channel API push a frame write event to a channel's framehook list.
00338  * \since 1.8
00339  *
00340  * \details After this function completes, the resulting frame that is returned could be anything,
00341  * even NULL.  There is nothing to keep up with after this function. If the frame is modified, the
00342  * framehook callback is in charge of any memory management associated with that modification.
00343  *
00344  * \pre The Channel must be locked during this function call.
00345  *
00346  * \param framehooks list to push event to.
00347  * \param frame being pushed to the framehook list.
00348  *
00349  * \return The resulting frame after being viewed and modified by the framehook callbacks.
00350  */
00351 struct ast_frame *ast_framehook_list_write_event(struct ast_framehook_list *framehooks, struct ast_frame *frame);
00352 
00353 /*!
00354  * \brief Determine if an framehook list is empty or not
00355  * \since 1.8
00356  * \pre The Channel must be locked during this function call.
00357  *
00358  * \param framehooks the framehook list
00359  * \retval 0, not empty
00360  * \retval 1, is empty
00361  */
00362 int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks);
00363 
00364 /*!
00365  * \brief Determine if a framehook list is free of active framehooks or not
00366  * \since 12.0.0
00367  * \pre The channel must be locked during this function call.
00368  *
00369  * \param framehooks the framehook list
00370  * \retval 0, not empty
00371  * \retval 1, is empty (aside from dying framehooks)
00372  *
00373  * \note This function is very similar to ast_framehook_list_is_empty, but it checks individual
00374  *       framehooks to see if they have been marked for destruction and doesn't count them if they are.
00375  */
00376 int ast_framehook_list_contains_no_active(struct ast_framehook_list *framehooks);
00377 
00378 /*!
00379  * \brief Determine if a framehook list is free of active framehooks consuming a specific type of frame
00380  * \since 12.3.0
00381  * \pre The channel must be locked during this function call.
00382  *
00383  * \param framehooks the framehook list
00384  * \retval 0, not empty
00385  * \retval 1, is empty (aside from dying framehooks)
00386  *
00387  * \note This function is very similar to ast_framehook_list_is_empty, but it checks individual
00388  *       framehooks to see if they have been marked for destruction and doesn't count them if they are.
00389  */
00390 int ast_framehook_list_contains_no_active_of_type(struct ast_framehook_list *framehooks,
00391    enum ast_frame_type type);
00392 
00393 #endif /* _AST_FRAMEHOOK_H */

Generated on Thu Apr 16 06:27:35 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6