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 #define AST_FRAMEHOOK_INTERFACE_VERSION 1 00203 /*! This interface is required for attaching a framehook to a channel. */ 00204 struct ast_framehook_interface { 00205 /*! framehook interface version number */ 00206 uint16_t version; 00207 /*! event_cb represents the function that will be called everytime an event occurs on the framehook. */ 00208 ast_framehook_event_callback event_cb; 00209 /*! destroy_cb is optional. This function is called immediately before the framehook 00210 * is destroyed to allow for stored_data cleanup. */ 00211 ast_framehook_destroy_callback destroy_cb; 00212 /*! This pointer can represent any custom data to be stored on the !framehook. This 00213 * data pointer will be provided during each event callback which allows the framehook 00214 * to store any stateful data associated with the application using the hook. */ 00215 void *data; 00216 }; 00217 00218 /*! 00219 * \brief Attach an framehook onto a channel for frame interception. 00220 * \since 1.8 00221 * 00222 * \param ast_channel, The channel to attach the hook on to. 00223 * \param framehook interface, The framehook's callback functions and stored data. 00224 * 00225 * \pre XXX The Channel must be locked during this function all. 00226 * 00227 * \note The data pointer is never touched by the framehook API except to 00228 * provide it during the event and destruction callbacks. It is entirely up to the 00229 * application using this API to manage the memory associated with the data pointer. 00230 * 00231 * \retval On success, positive id representing this hook on the channel 00232 * \retval On failure, -1 00233 */ 00234 int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i); 00235 00236 /*! 00237 * \brief Detach an framehook from a channel. 00238 * \since 1.8 00239 * 00240 * \pre XXX The Channel must be locked during this function all. 00241 * If this function is never called after attaching an framehook, 00242 * the framehook will be detached and destroyed during channel 00243 * destruction. 00244 * 00245 * \param The channel the framehook is attached to 00246 * \param The framehook's id 00247 * 00248 * \retval 0 success 00249 * \retval -1 framehook did not exist on the channel. This means the 00250 * framehook either never existed on the channel, or was already detached. 00251 */ 00252 int ast_framehook_detach(struct ast_channel *chan, int framehook_id); 00253 00254 /*! 00255 * \brief This is used by the channel API to detach and destroy all 00256 * framehooks on a channel during channel destruction. 00257 * \since 1.8 00258 * 00259 * \pre XXX The Channel must be locked during this function all. 00260 * 00261 * \param channel containing the framehook list to destroy. 00262 * \retval 0 success 00263 * \retval -1 failure 00264 */ 00265 int ast_framehook_list_destroy(struct ast_channel *chan); 00266 00267 /*! 00268 * \brief This is used by the channel API push a frame read event to a channel's framehook list. 00269 * \since 1.8 00270 * 00271 * \details After this function completes, the resulting frame that is returned could be anything, 00272 * even NULL. There is nothing to keep up with after this function. If the frame is modified, the 00273 * framehook callback is in charge of any memory management associated with that modification. 00274 * 00275 * \pre XXX The Channel must be locked during this function all. 00276 * 00277 * \param framehook list to push event to. 00278 * \param frame being pushed to the framehook list. 00279 * 00280 * \return The resulting frame after being viewed and modified by the framehook callbacks. 00281 */ 00282 struct ast_frame *ast_framehook_list_read_event(struct ast_framehook_list *framehooks, struct ast_frame *frame); 00283 00284 /*! 00285 * \brief This is used by the channel API push a frame write event to a channel's framehook list. 00286 * \since 1.8 00287 * 00288 * \details After this function completes, the resulting frame that is returned could be anything, 00289 * even NULL. There is nothing to keep up with after this function. If the frame is modified, the 00290 * framehook callback is in charge of any memory management associated with that modification. 00291 * 00292 * \pre XXX The Channel must be locked during this function all. 00293 * 00294 * \param framehook list to push event to. 00295 * \param frame being pushed to the framehook list. 00296 * 00297 * \return The resulting frame after being viewed and modified by the framehook callbacks. 00298 */ 00299 struct ast_frame *ast_framehook_list_write_event(struct ast_framehook_list *framehooks, struct ast_frame *frame); 00300 00301 /*! 00302 * \brief Determine if an framehook list is empty or not 00303 * \since 1.8 00304 * \pre XXX The Channel must be locked during this function all. 00305 * 00306 * \param the framehook list 00307 * \retval 0, not empty 00308 * \retval 1, is empty 00309 */ 00310 int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks); 00311 #endif /* _AST_FRAMEHOOK_H */