Asterisk - The Open Source Telephony Project GIT-master-3dee037
Asterisk FrameHook API

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.

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.

struct ast_framehook_interface interface = {
.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);
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
static struct ast_frame * hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
static void hook_destroy_cb(void *framedata)
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.
ast_framehook_detach(channel, id);
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
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.

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.

static void destroy_cb(void *data) {
}
static struct ast_frame *event_cb(struct ast_channel *chan,
struct ast_frame *frame,
void *data) {
int *id = data;
if (!frame) {
return frame;
}
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.
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 = {
.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.
*id = ast_framehook_attach(chan, &interface);
if (*id < 0) {
// framehook attach failed, free data
ast_free(id);
return -1;
}
return 0;
}
enum queue_result id
Definition: app_queue.c:1667
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
#define ast_channel_lock(chan)
Definition: channel.h:2968
#define ast_channel_unlock(chan)
Definition: channel.h:2969
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
Definition: framehook.h:151
@ AST_FRAMEHOOK_EVENT_WRITE
Definition: framehook.h:153
@ AST_FRAMEHOOK_EVENT_READ
Definition: framehook.h:152
#define LOG_NOTICE
Main Channel structure associated with a channel.
Data structure associated with a single frame of data.
union ast_frame::@226 data
enum ast_frame_type frametype
ast_framehook_destroy_callback destroy_cb
Definition: framehook.h:236
Definition: astman.c:222