summaryrefslogtreecommitdiff
path: root/include/asterisk/framehook.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asterisk/framehook.h')
-rw-r--r--include/asterisk/framehook.h311
1 files changed, 311 insertions, 0 deletions
diff --git a/include/asterisk/framehook.h b/include/asterisk/framehook.h
new file mode 100644
index 000000000..0b2e6cd95
--- /dev/null
+++ b/include/asterisk/framehook.h
@@ -0,0 +1,311 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * David Vossel <dvossel@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 FrameHook Architecture
+ */
+
+/*!
+
+\page AstFrameHookAPI Asterisk FrameHook API
+
+\section FrameHookFunctionality How FrameHooks Work
+ FrameHooks work by intercepting all frames being written and read off
+ a channel and allowing those frames to be viewed and manipulated within a
+ call back function. Frame interception occurs before any processing is
+ done on the frame, which means this hook can be used to transparently
+ manipulate a frame before it is read from the channel or written
+ to the tech_pvt. This API can be thought of as a layer between the
+ channel API and the Asterisk core when going in the READ direction, and
+ as a layer between the Channel API and the tech_pvt when going in the
+ WRITE direction.
+
+\section FrameHookAPIUsage How to Use an FrameHook
+ Attaching and detaching an FrameHook to a channel is very simple. There are only
+ two functions involved, ast_framehook_attach() which will return an id representing
+ the new FrameHook on the channel, and ast_framehook_detach() which signals the
+ FrameHook for detachment and destruction. Below is detailed information each of these
+ functions and their usage.
+
+\code
+ struct ast_framehook_interface interface = {
+ .version = AST_FRAMEHOOK_INTERFACE_VERSION,
+ .event_cb = hook_event_cb,
+ .destroy_cb = hook_destroy_cb,
+ .data = data, // where the data ptr points to any custom data used later by the hook cb.
+ };
+ int id = ast_framehook_attach(channel, &interface);
+\endcode
+
+ The ast_framehook_attach() function creates and attaches a new FrameHook onto
+ a channel. Once attached to the channel, the FrameHook will call the event_callback
+ function each time a frame is written or read on the channel. A custom data
+ pointer can be provided to this function to store on the FrameHook as well. This
+ pointer can be used to keep up with any statefull information associated with the FrameHook
+ and is provided during the event_callback function. The destroy_callback function is optional.
+ This function exists so any custom data stored on the FrameHook can be destroyed before
+ the Framehook if destroyed.
+
+\code
+ ast_framehook_detach(channel, id);
+\endcode
+
+ The ast_framehook_detach() function signals the FrameHook represented by an id to
+ be detached and destroyed on a channel. Since it is possible this function may be called
+ during the FrameHook's event callback, it is impossible to synchronously detach the
+ FrameHook from the channel during this function call. It is guaranteed that the next
+ event proceeding the ast_framehook_detach() will be of type AST_FRAMEHOOK_EVENT_DETACH,
+ and that after that event occurs no other event will ever be issued for that FrameHook.
+ Once the FrameHook is destroyed, the destroy callback function will be called if it was
+ provided. Note that if this function is never called, the FrameHook will be detached
+ on channel destruction.
+
+\section FrameHookAPICodeExample FrameHook Example Code
+ The example code below attaches an FrameHook on a channel, and then detachs it when
+ the first ast_frame is read or written to the event callback function. The Framehook's id
+ is stored on the FrameHook's data pointer so it can be detached within the callback.
+
+\code
+ static void destroy_cb(void *data) {
+ ast_free(data);
+ }
+
+ static struct ast_frame *event_cb(struct ast_channel *chan,
+ struct ast_frame *frame,
+ enum ast_framehook_event event,
+ void *data) {
+
+ int *id = data;
+
+ if (!frame) {
+ return frame;
+ }
+
+ if (event == AST_FRAMEHOOK_EVENT_WRITE) {
+ ast_log(LOG_NOTICE, "YAY we received a frame in the write direction, Type: %d\n", frame->frametype)
+ ast_framehook_detach(chan, id); // the channel is guaranteed to be locked during this function call.
+ } else if (event == AST_FRAMEHOOK_EVENT_READ) {
+ ast_log(LOG_NOTICE, "YAY we received a frame in the read direction: Type: %d\n", frame->frametype);
+ ast_framehook_detach(chan, id); // the channel is guaranteed to be locked during this function call.
+ }
+
+ return frame;
+ {
+
+ int some_function()
+ {
+ struct ast_framehook_interface interface = {
+ .version = AST_FRAMEHOOK_INTERFACE_VERSION,
+ .event_cb = hook_event_cb,
+ .destroy_cb = hook_destroy_cb,
+ };
+ int *id = ast_calloc(1, sizeof(int));
+
+ if (!id) {
+ return -1;
+ }
+
+ interface.data = id; // This data will be returned to us in the callbacks.
+
+ ast_channel_lock(chan);
+ *id = ast_framehook_attach(chan, &interface);
+ ast_channel_unlock(chan);
+
+ if (*id < 0) {
+ // framehook attach failed, free data
+ ast_free(id);
+ return -1;
+ }
+ return 0;
+ }
+\endcode
+*/
+
+#ifndef _AST_FRAMEHOOK_H_
+#define _AST_FRAMEHOOK_H_
+#include "asterisk/linkedlists.h"
+#include "asterisk/frame.h"
+
+struct ast_framehook;
+struct ast_framehook_list;
+
+/*!
+ * \brief These are the types of events that the framehook's event callback can receive
+ * \since 1.8
+ */
+enum ast_framehook_event {
+ AST_FRAMEHOOK_EVENT_READ, /*!< frame is intercepted in the read direction on the channel. */
+ AST_FRAMEHOOK_EVENT_WRITE, /*!< frame is intercepted on the write direction on the channel. */
+ AST_FRAMEHOOK_EVENT_ATTACHED, /*!< framehook is attached and running on the channel, the first message sent to event_cb. */
+ AST_FRAMEHOOK_EVENT_DETACHED /*!< framehook is detached from the channel, last message sent to event_cb. */
+};
+
+/*!
+ * \brief This callback is called every time an event occurs on the framehook.
+ * \since 1.8
+ *
+ * \details Two events are guaranteed to occur once the ast_framehook_attach()
+ * function is called. These events are AST_FRAMEHOOK_EVENT_ATTACHED, which occurs
+ * immediately after the framehook is attached to a channel, and
+ * AST_FRAMEHOOK_EVENT_DETACHED, which occurs right after the framehook is
+ * detached.
+ *
+ * It is completely valid for the frame variable to be set to NULL. Always do a NULL
+ * check on the frame before attempted to access it. When the frame variable is present,
+ * it is safe to view and manipulate that frame in any way possible. It is even safe
+ * to return a completely different frame, but when that occurs this function is in
+ * charge of freeing the previous frame.
+ *
+ * The ast_channel will always be locked during this callback. Never attempt to unlock the
+ * channel for any reason.
+ *
+ * \param channel, The ast_channel this framehook is attached to
+ * \param frame, The ast_frame being intercepted for viewing and manipulation
+ * \param event, The type of event which is occurring
+ * \param data, The data pointer provided at framehook initilization.
+ *
+ * \retval the resulting frame.
+ */
+typedef struct ast_frame *(*ast_framehook_event_callback)(
+ struct ast_channel *chan,
+ struct ast_frame *frame,
+ enum ast_framehook_event event,
+ void *data);
+
+/*!
+ * \brief This callback is called immediately before the framehook is destroyed.
+ * \since 1.8
+ * \note This function should be used to clean up any pointers pointing to the
+ * framehook structure as the framehook will be freed immediately afterwards.
+ *
+ * \param data, The data pointer provided at framehook initialization. This
+ * is a good place to clean up any state data allocated for the framehook stored in this
+ * pointer.
+ */
+typedef void (*ast_framehook_destroy_callback)(void *data);
+
+#define AST_FRAMEHOOK_INTERFACE_VERSION 1
+/*! This interface is required for attaching a framehook to a channel. */
+struct ast_framehook_interface {
+ /*! framehook interface version number */
+ uint16_t version;
+ /*! event_cb represents the function that will be called everytime an event occurs on the framehook. */
+ ast_framehook_event_callback event_cb;
+ /*! destroy_cb is optional. This function is called immediately before the framehook
+ * is destroyed to allow for stored_data cleanup. */
+ ast_framehook_destroy_callback destroy_cb;
+ /*! This pointer can represent any custom data to be stored on the !framehook. This
+ * data pointer will be provided during each event callback which allows the framehook
+ * to store any stateful data associated with the application using the hook. */
+ void *data;
+};
+
+/*!
+ * \brief Attach an framehook onto a channel for frame interception.
+ * \since 1.8
+ *
+ * \param ast_channel, The channel to attach the hook on to.
+ * \param framehook interface, The framehook's callback functions and stored data.
+*
+ * \pre XXX The Channel must be locked during this function all.
+ *
+ * \note The data pointer is never touched by the framehook API except to
+ * provide it during the event and destruction callbacks. It is entirely up to the
+ * application using this API to manage the memory associated with the data pointer.
+ *
+ * \retval On success, positive id representing this hook on the channel
+ * \retval On failure, -1
+ */
+int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i);
+
+/*!
+ * \brief Detach an framehook from a channel.
+ * \since 1.8
+ *
+ * \pre XXX The Channel must be locked during this function all.
+ * If this function is never called after attaching an framehook,
+ * the framehook will be detached and destroyed during channel
+ * destruction.
+ *
+ * \param The channel the framehook is attached to
+ * \param The framehook's id
+ *
+ * \retval 0 success
+ * \retval -1 framehook did not exist on the channel. This means the
+ * framehook either never existed on the channel, or was already detached.
+ */
+int ast_framehook_detach(struct ast_channel *chan, int framehook_id);
+
+/*!
+ * \brief This is used by the channel API to detach and destroy all
+ * framehooks on a channel during channel destruction.
+ * \since 1.8
+ *
+ * \pre XXX The Channel must be locked during this function all.
+ *
+ * \param channel containing the framehook list to destroy.
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_framehook_list_destroy(struct ast_channel *chan);
+
+/*!
+ * \brief This is used by the channel API push a frame read event to a channel's framehook list.
+ * \since 1.8
+ *
+ * \details After this function completes, the resulting frame that is returned could be anything,
+ * even NULL. There is nothing to keep up with after this function. If the frame is modified, the
+ * framehook callback is in charge of any memory management associated with that modification.
+ *
+ * \pre XXX The Channel must be locked during this function all.
+ *
+ * \param framehook list to push event to.
+ * \param frame being pushed to the framehook list.
+ *
+ * \return The resulting frame after being viewed and modified by the framehook callbacks.
+ */
+struct ast_frame *ast_framehook_list_read_event(struct ast_framehook_list *framehooks, struct ast_frame *frame);
+
+/*!
+ * \brief This is used by the channel API push a frame write event to a channel's framehook list.
+ * \since 1.8
+ *
+ * \details After this function completes, the resulting frame that is returned could be anything,
+ * even NULL. There is nothing to keep up with after this function. If the frame is modified, the
+ * framehook callback is in charge of any memory management associated with that modification.
+ *
+ * \pre XXX The Channel must be locked during this function all.
+ *
+ * \param framehook list to push event to.
+ * \param frame being pushed to the framehook list.
+ *
+ * \return The resulting frame after being viewed and modified by the framehook callbacks.
+ */
+struct ast_frame *ast_framehook_list_write_event(struct ast_framehook_list *framehooks, struct ast_frame *frame);
+
+/*!
+ * \brief Determine if an framehook list is empty or not
+ * \since 1.8
+ * \pre XXX The Channel must be locked during this function all.
+ *
+ * \param the framehook list
+ * \retval 0, not empty
+ * \retval 1, is empty
+ */
+int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks);
+#endif /* _AST_FRAMEHOOK_H */