[svn-commits] dvossel: branch dvossel/awesomehooks r287058 - in /team/dvossel/awesomehooks:...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Wed Sep 15 18:09:18 CDT 2010
Author: dvossel
Date: Wed Sep 15 18:09:14 2010
New Revision: 287058
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=287058
Log:
adds awesomehook interception points in ast_read, ast_write, and ast_indicate
Modified:
team/dvossel/awesomehooks/include/asterisk/awesomehook.h
team/dvossel/awesomehooks/main/awesomehook.c
team/dvossel/awesomehooks/main/channel.c
Modified: team/dvossel/awesomehooks/include/asterisk/awesomehook.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/awesomehooks/include/asterisk/awesomehook.h?view=diff&rev=287058&r1=287057&r2=287058
==============================================================================
--- team/dvossel/awesomehooks/include/asterisk/awesomehook.h (original)
+++ team/dvossel/awesomehooks/include/asterisk/awesomehook.h Wed Sep 15 18:09:14 2010
@@ -148,6 +148,8 @@
* even NULL. There is nothing to keep up with after this function. If the frame is modified, the
* awesomehook callback is in charge of any memory management associated with that modification.
*
+ * \note the list's channel owner _MUST_ be locked while calling this function.
+ *
* \param awesomehook list to push event to.
* \param frame being pushed to the awesomehook list.
*
@@ -162,12 +164,22 @@
* even NULL. There is nothing to keep up with after this function. If the frame is modified, the
* awesomehook callback is in charge of any memory management associated with that modification.
*
+ * \note the list's channel owner _MUST_ be locked while calling this function.
+ *
* \param awesomehook list to push event to.
* \param frame being pushed to the awesomehook list.
*
* \return The resulting frame after being viewed and modified by the awesomehook callbacks.
*/
struct ast_frame *ast_awesomehook_list_write_event(struct ast_awesomehook_list *awesomehooks, struct ast_frame *frame);
+
+/*!
+ * \brief Determine if an awesomehook list is empty or not
+ * \param the awesomehook list
+ * \retval 0, not empty
+ * \retval 1, is empty
+ */
+int ast_awesomehook_list_is_empty(struct ast_awesomehook_list *awesomehooks);
/*!
* \brief Set the awesomehook's custom data storage pointer.
Modified: team/dvossel/awesomehooks/main/awesomehook.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/awesomehooks/main/awesomehook.c?view=diff&rev=287058&r1=287057&r2=287058
==============================================================================
--- team/dvossel/awesomehooks/main/awesomehook.c (original)
+++ team/dvossel/awesomehooks/main/awesomehook.c Wed Sep 15 18:09:14 2010
@@ -18,7 +18,7 @@
/*! \file
*
- * \brief Awesomehooks Architecture
+ * \brief AwesomeHooks Architecture
*
* \author David Vossel <dvossel at digium.com>
*/
@@ -75,6 +75,38 @@
return 0;
}
+static void awesomehook_detach_and_destroy(struct ast_awesomehook *awesomehook)
+{
+ struct ast_frame *frame;
+ awesomehook_update_status(awesomehook, AST_AWESOMEHOOK_STATUS_DETACHED);
+ frame = awesomehook->event_cb(awesomehook, awesomehook->chan, NULL, AST_AWESOMEHOOK_EVENT_DETACHED);
+ /* never assume anything about this function. If you can return a frame during
+ * the detached event, then assume someone will. */
+ if (frame) {
+ ast_frfree(frame);
+ }
+ awesomehook->chan = NULL;
+ awesomehook_destroy(awesomehook);
+}
+
+static struct ast_frame *awesomehook_list_push_event(struct ast_awesomehook_list *awesomehooks, struct ast_frame *frame, enum ast_awesomehook_event event)
+{
+ struct ast_awesomehook *awesomehook;
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&awesomehooks->list, awesomehook, list) {
+ /* check to see if this hook was signaled for detachment, if so do not push the
+ * read/write event. Instead detach from list and destroy */
+ if (awesomehook->status == AST_AWESOMEHOOK_STATUS_DETACHED) {
+ AST_LIST_REMOVE_CURRENT(list);
+ awesomehook_detach_and_destroy(awesomehook);
+ continue;
+ }
+ frame = awesomehook->event_cb(awesomehook, awesomehook->chan, frame, event);
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
+ return frame;
+}
+
struct ast_awesomehook *ast_awesomehook_alloc(ast_awesomehook_event_callback event_cb, ast_awesomehook_destroy_callback destroy_cb)
{
struct ast_awesomehook *awesomehook;
@@ -111,20 +143,6 @@
return 0;
}
-static void awesomehook_detach_and_destroy(struct ast_awesomehook *awesomehook)
-{
- struct ast_frame *frame;
- awesomehook_update_status(awesomehook, AST_AWESOMEHOOK_STATUS_DETACHED);
- frame = awesomehook->event_cb(awesomehook, awesomehook->chan, NULL, AST_AWESOMEHOOK_EVENT_DETACHED);
- /* never assume anything about this function. If you can return a frame during
- * the detached event, then assume someone will. */
- if (frame) {
- ast_frfree(frame);
- }
- awesomehook->chan = NULL;
- awesomehook_destroy(awesomehook);
-}
-
int ast_awesomehook_signal_destroy(struct ast_awesomehook *awesomehook)
{
/* This signals to the channel to detach and destroy the hook on the next read or write */
@@ -145,22 +163,10 @@
return 0;
}
-static struct ast_frame *awesomehook_list_push_event(struct ast_awesomehook_list *awesomehooks, struct ast_frame *frame, enum ast_awesomehook_event event)
+
+int ast_awesomehook_list_is_empty(struct ast_awesomehook_list *awesomehooks)
{
- struct ast_awesomehook *awesomehook;
- AST_LIST_TRAVERSE_SAFE_BEGIN(&awesomehooks->list, awesomehook, list) {
- /* check to see if this hook was signaled for detachment, if so do not push the
- * read/write event. Instead detach from list and destroy */
- if (awesomehook->status == AST_AWESOMEHOOK_STATUS_DETACHED) {
- AST_LIST_REMOVE_CURRENT(list);
- awesomehook_detach_and_destroy(awesomehook);
- continue;
- }
- frame = awesomehook->event_cb(awesomehook, awesomehook->chan, frame, event);
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- return frame;
+ return AST_LIST_EMPTY(&awesomehooks->list) ? 1 : 0;
}
struct ast_frame *ast_awesomehook_list_write_event(struct ast_awesomehook_list *awesomehooks, struct ast_frame *frame)
Modified: team/dvossel/awesomehooks/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/awesomehooks/main/channel.c?view=diff&rev=287058&r1=287057&r2=287058
==============================================================================
--- team/dvossel/awesomehooks/main/channel.c (original)
+++ team/dvossel/awesomehooks/main/channel.c Wed Sep 15 18:09:14 2010
@@ -2633,6 +2633,8 @@
chan->audiohooks = NULL;
}
+ ast_awesomehook_list_destroy(&chan->awesomehooks);
+
ast_autoservice_stop(chan);
if (chan->masq) {
@@ -3749,6 +3751,10 @@
* easily detect when ast_read() is called without properly using ast_waitfor().
*/
chan->fdno = -1;
+
+ /* Perform the awesomehook read event here. After the frame enters the awesomehook list
+ * there is no telling what will happen, <insert mad scientist laugh here>!!! */
+ f = ast_awesomehook_list_read_event(&chan->awesomehooks, f);
if (f) {
struct ast_frame *readq_tail = AST_LIST_LAST(&chan->readq);
@@ -4143,14 +4149,42 @@
enum ast_control_frame_type condition = _condition;
struct ast_tone_zone_sound *ts = NULL;
int res;
+ /* this frame is used by awesomehooks. if it is set, we must free it at the end of this function */
+ struct ast_frame *awesome_frame = NULL;
ast_channel_lock(chan);
/* Don't bother if the channel is about to go away, anyway. */
if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
ast_channel_unlock(chan);
- return -1;
- }
+ res = -1;
+ goto indicate_cleanup;
+ }
+
+ if (!ast_awesomehook_list_is_empty(&chan->awesomehooks)) {
+ /* Do awesomehooks now, do it, go, go now */
+ struct ast_frame frame = {
+ .frametype = AST_FRAME_CONTROL,
+ .subclass.integer = condition,
+ .data.ptr = (void *) data, /* this cast from const is only okay because we do the ast_frdup below */
+ .datalen = datalen
+ };
+
+ /* we have now committed to freeing this frame */
+ awesome_frame = ast_frdup(&frame);
+
+ /* who knows what we will get back! the anticipation is killing me. */
+ if (!(awesome_frame = ast_awesomehook_list_read_event(&chan->awesomehooks, &frame))) {
+ ast_channel_unlock(chan);
+ res = 0;
+ goto indicate_cleanup;
+ }
+
+ condition = awesome_frame->subclass.integer;
+ data = awesome_frame->data.ptr;
+ datalen = awesome_frame->datalen;
+ }
+
switch (condition) {
case AST_CONTROL_CONNECTED_LINE:
{
@@ -4196,7 +4230,8 @@
if (is_visible_indication(condition)) {
chan->visible_indication = condition;
}
- return 0;
+ res = 0;
+ goto indicate_cleanup;
}
/* The channel driver does not support this indication, let's fake
@@ -4208,14 +4243,16 @@
if (_condition < 0) {
/* Stop any tones that are playing */
ast_playtones_stop(chan);
- return 0;
+ res = 0;
+ goto indicate_cleanup;
}
/* Handle conditions that we have tones for. */
switch (condition) {
case _XXX_AST_CONTROL_T38:
/* deprecated T.38 control frame */
- return -1;
+ res = -1;
+ goto indicate_cleanup;
case AST_CONTROL_T38_PARAMETERS:
/* there is no way to provide 'default' behavior for these
* control frames, so we need to return failure, but there
@@ -4224,7 +4261,7 @@
* so just return right now. in addition, we want to return
* whatever value the channel driver returned, in case it
* has some meaning.*/
- return res;
+ goto indicate_cleanup;
case AST_CONTROL_RINGING:
ts = ast_get_indication_tone(chan->zone, "ring");
/* It is common practice for channel drivers to return -1 if trying
@@ -4286,6 +4323,11 @@
ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
}
+indicate_cleanup:
+ if (awesome_frame) {
+ ast_frfree(awesome_frame);
+ }
+
return res;
}
@@ -4572,6 +4614,14 @@
res = 0; /* XXX explain, why 0 ? */
goto done;
}
+
+ /* Perform the awesomehook write event here. After the frame enters the awesomehook list
+ * there is no telling what will happen, how awesome is that!!! */
+ if (!(fr = ast_awesomehook_list_write_event(&chan->awesomehooks, fr))) {
+ res = 0;
+ goto done;
+ }
+
if (chan->generatordata && (!fr->src || strcasecmp(fr->src, "ast_prod"))) {
if (ast_test_flag(chan, AST_FLAG_WRITE_INT)) {
ast_deactivate_generator(chan);
More information about the svn-commits
mailing list