[asterisk-commits] dvossel: branch dvossel/awesomehooks r286934 - in /team/dvossel/awesomehooks:...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Sep 15 14:22:54 CDT 2010


Author: dvossel
Date: Wed Sep 15 14:22:50 2010
New Revision: 286934

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=286934
Log:
adds functionality for pushing events to awesomehook lists.

Modified:
    team/dvossel/awesomehooks/include/asterisk/awesomehook.h
    team/dvossel/awesomehooks/main/awesomehook.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=286934&r1=286933&r2=286934
==============================================================================
--- team/dvossel/awesomehooks/include/asterisk/awesomehook.h (original)
+++ team/dvossel/awesomehooks/include/asterisk/awesomehook.h Wed Sep 15 14:22:50 2010
@@ -37,7 +37,7 @@
 };
 
 enum ast_awesomehook_event {
-	AST_AWESOMEHOOK_NO_EVENTS,
+	AST_AWESOMEHOOK_EVENT_NOOP, /*!< This is a NO-OP event. It only exists to initilized the awesomehook->last_event variable*/
 	AST_AWESOMEHOOK_EVENT_READ, /*!< frame is intercepted in the read direction on the channel. */
 	AST_AWESOMEHOOK_EVENT_WRITE, /*!< frame is intercepted on the write direction on the channel. */
 	AST_AWESOMEHOOK_EVENT_ATTACHED, /*!< the awesomehook is attached and running on the channel. */
@@ -54,8 +54,25 @@
  * immediately after the awesomehook is attached to a channel, and
  * AST_AWESOMEHOOK_EVENT_DETACHED, which occurs right after the awesomehook is 
  * detached.
+ *
+ * It is _NOT_ safe to assume the channel or the frame are ever not NULL. Always perform
+ * a NULL check before performing any action on either of these objects.
+ *
+ * When the channel variable is present, it is safe to assume it will always be locked.
+ * Never attempt to unlock the channel variable during this callback.
+ *
+ * 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.
+ *
+ * \param awesomehook, The awesomehook associated with this callback.
+ * \param channel, The ast_channel this awesomehook is attached to.
+ * \param frame, The ast_frame being intercepted for viewing and manipulation
+ * \param event, The type of event which is occurring
+ *
+ * \retval the resulting frame.
  */
-typedef int (*ast_awesomehook_event_callback)(struct ast_awesomehook *awesomehook,
+typedef struct ast_frame *(*ast_awesomehook_event_callback)(struct ast_awesomehook *awesomehook,
 	struct ast_channel *chan,
 	struct ast_frame *frame,
 	enum ast_awesomehook_event event);
@@ -125,9 +142,32 @@
 int ast_awesomehook_list_destroy(struct ast_awesomehook_list *awesomehooks);
 
 /*!
- * \brief Return the status of an awesomehook.
+ * \brief This is used by the channel API push a frame read event to a channel's awesomehook list.
+ *
+ * \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
+ * awesomehook callback is in charge of any memory management associated with that modification.
+ *
+ * \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.
  */
-enum ast_awesomehook_status ast_awesomehook_get_status(struct ast_awesomehook *awesomehook);
+struct ast_frame *ast_awesomehook_list_read_event(struct ast_awesomehook_list *awesomehooks, struct ast_frame *frame);
+
+/*!
+ * \brief This is used by the channel API push a frame write event to a channel's awesomehook list.
+ *
+ * \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
+ * awesomehook callback is in charge of any memory management associated with that modification.
+ *
+ * \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 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=286934&r1=286933&r2=286934
==============================================================================
--- team/dvossel/awesomehooks/main/awesomehook.c (original)
+++ team/dvossel/awesomehooks/main/awesomehook.c Wed Sep 15 14:22:50 2010
@@ -84,13 +84,14 @@
 	awesomehook->event_cb = event_cb;
 	awesomehook->destroy_cb = destroy_cb;
 	awesomehook->status = AST_AWESOMEHOOK_STATUS_INIT;
-	awesomehook->last_event = AST_AWESOMEHOOK_NO_EVENTS;
+	awesomehook->last_event = AST_AWESOMEHOOK_EVENT_NOOP;
 	ast_mutex_init(&awesomehook->lock);
 	return awesomehook;
 }
 
 int ast_awesomehook_attach(struct ast_awesomehook *awesomehook, struct ast_channel *chan)
 {
+	struct ast_frame *frame;
 	ast_channel_lock(chan);
 	AST_LIST_INSERT_TAIL(&chan->awesomehooks.list, awesomehook, list);
 	awesomehook->chan = chan;
@@ -99,9 +100,29 @@
 	awesomehook_update_status(awesomehook, AST_AWESOMEHOOK_STATUS_ATTACHED);
 
 	/* tell the event callback we're live and rocking */
-	awesomehook->event_cb(awesomehook, awesomehook->chan, NULL, AST_AWESOMEHOOK_EVENT_ATTACHED);
+	frame = awesomehook->event_cb(awesomehook, awesomehook->chan, NULL, AST_AWESOMEHOOK_EVENT_ATTACHED);
+
+	/* never assume anything about this function. If you can return a frame during
+	 * the attached event, then assume someone will. */
+	if (frame) {
+		ast_frfree(frame);
+	}
 
 	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)
@@ -117,19 +138,39 @@
 
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&awesomehooks->list, awesomehook, list) {
 		AST_LIST_REMOVE_CURRENT(list);
-		awesomehook_update_status(awesomehook, AST_AWESOMEHOOK_STATUS_DETACHED);
-		awesomehook->event_cb(awesomehook, awesomehook->chan, NULL, AST_AWESOMEHOOK_EVENT_DETACHED);
-		awesomehook->chan = NULL;
-		awesomehook_destroy(awesomehook);
+		awesomehook_detach_and_destroy(awesomehook);
 	}
 	AST_LIST_TRAVERSE_SAFE_END;
 
 	return 0;
 }
 
-enum ast_awesomehook_status ast_awesomehook_get_status(struct ast_awesomehook *awesomehook)
+static struct ast_frame *awesomehook_list_push_event(struct ast_awesomehook_list *awesomehooks, struct ast_frame *frame, enum ast_awesomehook_event event)
 {
-	return awesomehook->status;
+	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_frame *ast_awesomehook_list_write_event(struct ast_awesomehook_list *awesomehooks, struct ast_frame *frame)
+{
+	return awesomehook_list_push_event(awesomehooks, frame, AST_AWESOMEHOOK_EVENT_WRITE);
+}
+
+struct ast_frame *ast_awesomehook_list_read_event(struct ast_awesomehook_list *awesomehooks, struct ast_frame *frame)
+{
+	return awesomehook_list_push_event(awesomehooks, frame, AST_AWESOMEHOOK_EVENT_READ);
 }
 
 int ast_awesomehook_set_datastore(struct ast_awesomehook *awesomehook, void *data)




More information about the asterisk-commits mailing list