Undoing framehook support. Issues were uncovered by Bamboo.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@413668 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/97/197/1
Joshua Colp 11 years ago
parent 3b3e4b9b95
commit e2ed86e4ca

@ -288,12 +288,6 @@ static struct ast_frame *native_rtp_framehook(struct ast_channel *chan, struct a
return f; return f;
} }
/*! \brief Callback function which informs upstream if we are consuming a frame of a specific type */
static int native_rtp_framehook_consume(void *data, enum ast_frame_type type)
{
return (type == AST_FRAME_CONTROL ? 1 : 0);
}
/*! \brief Internal helper function which checks whether the channels are compatible with our native bridging */ /*! \brief Internal helper function which checks whether the channels are compatible with our native bridging */
static int native_rtp_bridge_capable(struct ast_channel *chan) static int native_rtp_bridge_capable(struct ast_channel *chan)
{ {
@ -398,7 +392,6 @@ static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_
static struct ast_framehook_interface hook = { static struct ast_framehook_interface hook = {
.version = AST_FRAMEHOOK_INTERFACE_VERSION, .version = AST_FRAMEHOOK_INTERFACE_VERSION,
.event_cb = native_rtp_framehook, .event_cb = native_rtp_framehook,
.consume_cb = native_rtp_framehook_consume,
}; };
if (!data) { if (!data) {

@ -1049,8 +1049,8 @@ enum {
*/ */
AST_SOFTHANGUP_EXPLICIT = (1 << 5), AST_SOFTHANGUP_EXPLICIT = (1 << 5),
/*! /*!
* Used to request that the bridge core re-evaluate the current * Used to break a bridge so the channel can be spied upon
* bridging technology in use by the bridge this channel is in. * instead of actually hanging up.
*/ */
AST_SOFTHANGUP_UNBRIDGE = (1 << 6), AST_SOFTHANGUP_UNBRIDGE = (1 << 6),
/*! /*!
@ -4401,16 +4401,6 @@ const char *ast_channel_oldest_linkedid(const char *a, const char *b);
*/ */
int ast_channel_has_audio_frame_or_monitor(struct ast_channel *chan); int ast_channel_has_audio_frame_or_monitor(struct ast_channel *chan);
/*!
* \brief Check if the channel has any active hooks that require audio.
* \since 12.3.0
*
* \param chan The channel to check.
*
* \retval non-zero if channel has active audiohooks, audio framehooks, or monitor.
*/
int ast_channel_has_hook_requiring_audio(struct ast_channel *chan);
/*! /*!
* \brief Removes the trailing identifiers from a channel name string * \brief Removes the trailing identifiers from a channel name string
* \since 12.0.0 * \since 12.0.0

@ -25,114 +25,114 @@
\page AstFrameHookAPI Asterisk FrameHook API \page AstFrameHookAPI Asterisk FrameHook API
\section FrameHookFunctionality How FrameHooks Work \section FrameHookFunctionality How FrameHooks Work
FrameHooks work by intercepting all frames being written and read off FrameHooks work by intercepting all frames being written and read off
a channel and allowing those frames to be viewed and manipulated within a a channel and allowing those frames to be viewed and manipulated within a
call back function. Frame interception occurs before any processing is call back function. Frame interception occurs before any processing is
done on the frame, which means this hook can be used to transparently 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 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 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 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 as a layer between the Channel API and the tech_pvt when going in the
WRITE direction. WRITE direction.
\section FrameHookAPIUsage How to Use an FrameHook \section FrameHookAPIUsage How to Use an FrameHook
Attaching and detaching an FrameHook to a channel is very simple. There are only 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 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 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 FrameHook for detachment and destruction. Below is detailed information each of these
functions and their usage. functions and their usage.
\code \code
struct ast_framehook_interface interface = { struct ast_framehook_interface interface = {
.version = AST_FRAMEHOOK_INTERFACE_VERSION, .version = AST_FRAMEHOOK_INTERFACE_VERSION,
.event_cb = hook_event_cb, .event_cb = hook_event_cb,
.destroy_cb = hook_destroy_cb, .destroy_cb = hook_destroy_cb,
.data = data, // where the data ptr points to any custom data used later by the hook 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 id = ast_framehook_attach(channel, &interface);
\endcode \endcode
The ast_framehook_attach() function creates and attaches a new FrameHook onto 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 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 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 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 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. 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 This function exists so any custom data stored on the FrameHook can be destroyed before
the Framehook if destroyed. the Framehook if destroyed.
\code \code
ast_framehook_detach(channel, id); ast_framehook_detach(channel, id);
\endcode \endcode
The ast_framehook_detach() function signals the FrameHook represented by an id to 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 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 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 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, 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. 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 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 provided. Note that if this function is never called, the FrameHook will be detached
on channel destruction. on channel destruction.
\section FrameHookAPICodeExample FrameHook Example Code \section FrameHookAPICodeExample FrameHook Example Code
The example code below attaches an FrameHook on a channel, and then detachs it when 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 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. is stored on the FrameHook's data pointer so it can be detached within the callback.
\code \code
static void destroy_cb(void *data) { static void destroy_cb(void *data) {
ast_free(data); ast_free(data);
} }
static struct ast_frame *event_cb(struct ast_channel *chan, static struct ast_frame *event_cb(struct ast_channel *chan,
struct ast_frame *frame, struct ast_frame *frame,
enum ast_framehook_event event, enum ast_framehook_event event,
void *data) { void *data) {
int *id = data; int *id = data;
if (!frame) { if (!frame) {
return frame; return frame;
} }
if (event == AST_FRAMEHOOK_EVENT_WRITE) { 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_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_framehook_detach(chan, id); // the channel is guaranteed to be locked during this function call.
} else if (event == AST_FRAMEHOOK_EVENT_READ) { } 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_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. ast_framehook_detach(chan, id); // the channel is guaranteed to be locked during this function call.
} }
return frame; return frame;
{ {
int some_function() int some_function()
{ {
struct ast_framehook_interface interface = { struct ast_framehook_interface interface = {
.version = AST_FRAMEHOOK_INTERFACE_VERSION, .version = AST_FRAMEHOOK_INTERFACE_VERSION,
.event_cb = hook_event_cb, .event_cb = hook_event_cb,
.destroy_cb = hook_destroy_cb, .destroy_cb = hook_destroy_cb,
}; };
int *id = ast_calloc(1, sizeof(int)); int *id = ast_calloc(1, sizeof(int));
if (!id) { if (!id) {
return -1; return -1;
} }
interface.data = id; // This data will be returned to us in the callbacks. interface.data = id; // This data will be returned to us in the callbacks.
ast_channel_lock(chan); ast_channel_lock(chan);
*id = ast_framehook_attach(chan, &interface); *id = ast_framehook_attach(chan, &interface);
ast_channel_unlock(chan); ast_channel_unlock(chan);
if (*id < 0) { if (*id < 0) {
// framehook attach failed, free data // framehook attach failed, free data
ast_free(id); ast_free(id);
return -1; return -1;
} }
return 0; return 0;
} }
\endcode \endcode
*/ */
@ -199,20 +199,7 @@ typedef struct ast_frame *(*ast_framehook_event_callback)(
*/ */
typedef void (*ast_framehook_destroy_callback)(void *data); typedef void (*ast_framehook_destroy_callback)(void *data);
/*! #define AST_FRAMEHOOK_INTERFACE_VERSION 1
* \brief This callback is called to determine if the framehook is currently consuming
* frames of a given type
* \since 12
*
* \param data, The data pointer provided at framehook initilization.
* \param type, The type of frame.
*
* \return 0 if frame type is being ignored
* \return 1 if frame type is not being ignored
*/
typedef int (*ast_framehook_consume_callback)(void *data, enum ast_frame_type type);
#define AST_FRAMEHOOK_INTERFACE_VERSION 2
/*! This interface is required for attaching a framehook to a channel. */ /*! This interface is required for attaching a framehook to a channel. */
struct ast_framehook_interface { struct ast_framehook_interface {
/*! framehook interface version number */ /*! framehook interface version number */
@ -222,10 +209,6 @@ struct ast_framehook_interface {
/*! destroy_cb is optional. This function is called immediately before the framehook /*! destroy_cb is optional. This function is called immediately before the framehook
* is destroyed to allow for stored_data cleanup. */ * is destroyed to allow for stored_data cleanup. */
ast_framehook_destroy_callback destroy_cb; ast_framehook_destroy_callback destroy_cb;
/*! consume_cb is optional. This function is called to query whether the framehook is consuming
* frames of a specific type at this time. If this callback is not implemented it is assumed that the
* framehook will consume frames of all types. */
ast_framehook_consume_callback consume_cb;
/*! This pointer can represent any custom data to be stored on the !framehook. This /*! 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 * 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. */ * to store any stateful data associated with the application using the hook. */
@ -340,19 +323,4 @@ int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks);
*/ */
int ast_framehook_list_contains_no_active(struct ast_framehook_list *framehooks); int ast_framehook_list_contains_no_active(struct ast_framehook_list *framehooks);
/*!
* \brief Determine if a framehook list is free of active framehooks consuming a specific type of frame
* \since 12.3.0
* \pre The channel must be locked during this function call.
*
* \param framehooks the framehook list
* \retval 0, not empty
* \retval 1, is empty (aside from dying framehooks)
*
* \note This function is very similar to ast_framehook_list_is_empty, but it checks individual
* framehooks to see if they have been marked for destruction and doesn't count them if they are.
*/
int ast_framehook_list_contains_no_active_of_type(struct ast_framehook_list *framehooks,
enum ast_frame_type type);
#endif /* _AST_FRAMEHOOK_H */ #endif /* _AST_FRAMEHOOK_H */

@ -2614,12 +2614,6 @@ static struct ast_frame *transfer_target_framehook_cb(struct ast_channel *chan,
return frame; return frame;
} }
/*! \brief Callback function which informs upstream if we are consuming a frame of a specific type */
static int transfer_target_framehook_consume(void *data, enum ast_frame_type type)
{
return (type == AST_FRAME_CONTROL ? 1 : 0);
}
static void transfer_target_framehook_destroy_cb(void *data) static void transfer_target_framehook_destroy_cb(void *data)
{ {
struct attended_transfer_properties *props = data; struct attended_transfer_properties *props = data;
@ -2853,7 +2847,6 @@ static int attach_framehook(struct attended_transfer_properties *props, struct a
.version = AST_FRAMEHOOK_INTERFACE_VERSION, .version = AST_FRAMEHOOK_INTERFACE_VERSION,
.event_cb = transfer_target_framehook_cb, .event_cb = transfer_target_framehook_cb,
.destroy_cb = transfer_target_framehook_destroy_cb, .destroy_cb = transfer_target_framehook_destroy_cb,
.consume_cb = transfer_target_framehook_consume,
}; };
ao2_ref(props, +1); ao2_ref(props, +1);

@ -2668,13 +2668,6 @@ int ast_channel_has_audio_frame_or_monitor(struct ast_channel *chan)
|| !ast_framehook_list_contains_no_active(ast_channel_framehooks(chan)); || !ast_framehook_list_contains_no_active(ast_channel_framehooks(chan));
} }
int ast_channel_has_hook_requiring_audio(struct ast_channel *chan)
{
return ast_channel_monitor(chan)
|| !ast_audiohook_write_list_empty(ast_channel_audiohooks(chan))
|| !ast_framehook_list_contains_no_active_of_type(ast_channel_framehooks(chan), AST_FRAME_VOICE);
}
static void destroy_hooks(struct ast_channel *chan) static void destroy_hooks(struct ast_channel *chan)
{ {
if (ast_channel_audiohooks(chan)) { if (ast_channel_audiohooks(chan)) {

@ -160,10 +160,6 @@ int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interfac
ast_frfree(frame); ast_frfree(frame);
} }
if (ast_channel_is_bridged(chan)) {
ast_softhangup_nolock(chan, AST_SOFTHANGUP_UNBRIDGE);
}
return framehook->id; return framehook->id;
} }
@ -189,10 +185,6 @@ int ast_framehook_detach(struct ast_channel *chan, int id)
} }
AST_LIST_TRAVERSE_SAFE_END; AST_LIST_TRAVERSE_SAFE_END;
if (!res && ast_channel_is_bridged(chan)) {
ast_softhangup_nolock(chan, AST_SOFTHANGUP_UNBRIDGE);
}
return res; return res;
} }
@ -222,12 +214,6 @@ int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks)
} }
int ast_framehook_list_contains_no_active(struct ast_framehook_list *framehooks) int ast_framehook_list_contains_no_active(struct ast_framehook_list *framehooks)
{
return ast_framehook_list_contains_no_active_of_type(framehooks, 0);
}
int ast_framehook_list_contains_no_active_of_type(struct ast_framehook_list *framehooks,
enum ast_frame_type type)
{ {
struct ast_framehook *cur; struct ast_framehook *cur;
@ -243,9 +229,6 @@ int ast_framehook_list_contains_no_active_of_type(struct ast_framehook_list *fra
if (cur->detach_and_destroy_me) { if (cur->detach_and_destroy_me) {
continue; continue;
} }
if (type && cur->i.consume_cb && !cur->i.consume_cb(cur->i.data, type)) {
continue;
}
return 0; return 0;
} }

Loading…
Cancel
Save