[asterisk-commits] dlee: branch dlee/stasis-app r381838 - in /team/dlee/stasis-app: apps/ includ...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Feb 20 14:23:49 CST 2013
Author: dlee
Date: Wed Feb 20 14:23:46 2013
New Revision: 381838
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=381838
Log:
Split app and control structs
Modified:
team/dlee/stasis-app/apps/app_stasis.c
team/dlee/stasis-app/include/asterisk/app_stasis.h
Modified: team/dlee/stasis-app/apps/app_stasis.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/apps/app_stasis.c?view=diff&rev=381838&r1=381837&r2=381838
==============================================================================
--- team/dlee/stasis-app/apps/app_stasis.c (original)
+++ team/dlee/stasis-app/apps/app_stasis.c Wed Feb 20 14:23:46 2013
@@ -72,11 +72,19 @@
#define APPS_NUM_BUCKETS 127
/*!
+ * \brief Number of buckets for the Stasis application hash table. Remember to
+ * keep it a prime number!
+ */
+#define CONTROLS_NUM_BUCKETS 127
+
+/*!
* \brief Stasis application container. Please call stasis_apps() instead of
* directly accessing.
*/
struct ao2_container *__stasis_apps;
+struct ao2_container *__stasis_controls;
+
/*! Ref-counting accessor for the stasis applications container */
static struct ao2_container *stasis_apps(void)
{
@@ -84,7 +92,12 @@
return __stasis_apps;
}
-/*! \brief Stasis application ref */
+static struct ao2_container *stasis_contols(void)
+{
+ ao2_ref(__stasis_controls, +1);
+ return __stasis_controls;
+}
+
struct stasis_app {
/*! Name of the Stasis application */
char *name;
@@ -92,69 +105,115 @@
stasis_app_cb handler;
/*! Opaque data to hand to callback function. */
void *data;
+};
+
+/*! Destructor for \ref stasis_app. */
+static void app_dtor(void *obj)
+{
+ struct stasis_app *app = obj;
+ ast_free(app->name);
+}
+
+/*! Constructor for \ref stasis_app. */
+static struct stasis_app *app_create(const char *name, stasis_app_cb handler, void *data)
+{
+ RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
+
+ ast_assert(name != NULL);
+ ast_assert(handler != NULL);
+
+ app = ao2_alloc_options(sizeof(*app), app_dtor, AO2_ALLOC_OPT_LOCK_MUTEX);
+
+ if (!app) {
+ return NULL;
+ }
+
+ if (!(app->name = ast_strdup(name))) {
+ return NULL;
+ }
+
+ app->handler = handler;
+ app->data = data;
+
+ ao2_ref(app, +1);
+ return app;
+}
+
+/*! AO2 hash function for \ref stasis_app */
+static int app_hash(const void *obj, const int flags)
+{
+ const struct stasis_app *app = obj;
+ const char *name = flags & OBJ_KEY ? obj : app->name;
+
+ return ast_hashtab_hash_string(name);
+}
+
+/*! AO2 comparison function for \ref stasis_app */
+static int app_compare(void *lhs, void *rhs, int flags)
+{
+ const struct stasis_app *lhs_app = lhs;
+ const struct stasis_app *rhs_app = rhs;
+ const char *rhs_name = flags & OBJ_KEY ? rhs : rhs_app->name;
+
+ if (strcmp(lhs_app->name, rhs_name) == 0) {
+ return CMP_MATCH | CMP_STOP;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ * \brief Send a message to the given application.
+ * \param app App to send the message to.
+ * \param message Message to send.
+ */
+static void app_send(struct stasis_app *app, struct ast_json *message)
+{
+ app->handler(app->data, app->name, message);
+}
+
+struct stasis_app_control {
+ /*! Uniqueid of the associated channel */
+ char *channel_uniqueid;
/*!
* When set, /c app_stasis should exit and continue in the dialplan.
*/
int continue_to_dialplan:1;
- /*!
- * When set, indicates \c app_stasis is currently running.
- */
- int is_in_app_stasis:1;
};
-/*! Destructor for \ref stasis_app. */
-static void app_dtor(void *obj)
-{
- struct stasis_app *app = obj;
- ast_free(app->name);
-}
-
-/*! Constructor for \ref stasis_app. */
-static struct stasis_app *app_create(const char *name, stasis_app_cb handler, void *data)
-{
- RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
-
- ast_assert(name != NULL);
- ast_assert(handler != NULL);
-
- app = ao2_alloc_options(sizeof(*app), app_dtor, AO2_ALLOC_OPT_LOCK_MUTEX);
-
- if (!app) {
- return NULL;
- }
-
- if (!(app->name = ast_strdup(name))) {
- return NULL;
- }
-
- app->handler = handler;
- app->data = data;
-
- ao2_ref(app, +1);
- return app;
-}
-
-/*! AO2 hash function for \ref stasis_app */
-static int app_hash(const void *obj, const int flags)
-{
- const struct stasis_app *app = obj;
- const char *name = flags & OBJ_KEY ? obj : app->name;
-
- return ast_hashtab_hash_string(name);
-}
-
-/*! AO2 comparison function for \ref stasis_app */
-static int app_compare(void *lhs, void *rhs, int flags)
-{
- const struct stasis_app *lhs_app = lhs;
- const struct stasis_app *rhs_app = rhs;
- const char *rhs_name = flags & OBJ_KEY ? rhs : rhs_app->name;
-
- if (strcmp(lhs_app->name, rhs_name) == 0) {
- return CMP_MATCH | CMP_STOP;
- } else {
- return 0;
- }
+static void stasis_app_control_dtor(void *obj)
+{
+ struct stasis_app_control *control = obj;
+ ast_free(control->channel_uniqueid);
+}
+
+static struct stasis_app_control *control_create(const char *uniqueid)
+{
+ RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+
+ control = ao2_alloc(sizeof(*control), stasis_app_control_dtor);
+ if (!control) {
+ return NULL;
+ }
+
+ control->channel_uniqueid = ast_strdup(uniqueid);
+ if (!control->channel_uniqueid) {
+ return NULL;
+ }
+
+ ao2_ref(control, +1);
+ return control;
+}
+
+struct stasis_app_control *stasis_app_control_find_by_channel(const struct ast_channel *chan)
+{
+ RAII_VAR(struct ao2_container *, controls, NULL, ao2_cleanup);
+ if (chan == NULL) {
+ return NULL;
+ }
+
+ controls = stasis_contols();
+ return ao2_find(controls, ast_channel_uniqueid(chan), OBJ_KEY);
}
/*!
@@ -166,56 +225,20 @@
* \return Zero to remain in \c Stasis
* \return Non-zero to continue in the dialplan
*/
-static int app_continue_test_and_reset(struct stasis_app *app)
-{
- int r;
- SCOPED_AO2LOCK(lock, app);
-
- r = app->continue_to_dialplan;
- app->continue_to_dialplan = 0;
- return r;
-}
-
-/*!
- * \brief Atomically set the is_in_app_stasis flag on an \a app.
- * \param app Application to put into stasis
- * \param is_in_app_stasis New value of is_in_app_stasis
- */
-static void app_set_is_in_app_stasis(struct stasis_app *app, int is_in_app_stasis)
-{
- if (app) {
- SCOPED_AO2LOCK(lock, app);
- app->is_in_app_stasis = is_in_app_stasis;
- }
-}
-
-/*!
- * \brief Send a message to the given application.
- * \param app App to send the message to.
- * \param message Message to send.
- */
-static void app_send(struct stasis_app *app, struct ast_json *message)
-{
- app->handler(app->data, app->name, message);
-}
-
-struct stasis_app *stasis_app_find_by_channel(struct ast_channel *chan)
-{
- RAII_VAR(struct ao2_container *, handlers, NULL, ao2_cleanup);
- if (chan == NULL) {
- return NULL;
- }
-
- handlers = stasis_apps();
- return ao2_find(handlers, ast_channel_uniqueid(chan), OBJ_KEY);
-}
-
-void stasis_app_continue(struct stasis_app *handler)
-{
- SCOPED_AO2LOCK(lock, handler);
- if (handler->is_in_app_stasis) {
- handler->continue_to_dialplan = 1;
- }
+static int control_continue_test_and_reset(struct stasis_app_control *control)
+{
+ int r;
+ SCOPED_AO2LOCK(lock, control);
+
+ r = control->continue_to_dialplan;
+ control->continue_to_dialplan = 0;
+ return r;
+}
+
+void stasis_app_control_continue(struct stasis_app_control *control)
+{
+ SCOPED_AO2LOCK(lock, control);
+ control->continue_to_dialplan = 1;
}
struct ast_json *stasis_app_event_create(const char *event_name, const struct ast_channel_snapshot *channel_info, const struct ast_json *extra_info) {
@@ -323,16 +346,17 @@
}
/*!
- * \brief RAII_VAR dtor, which unsets \c is_in_app_stasis in addition to
- * ao2_cleanup().
- * \param obj \ref stasis_app object to clean up.
- */
-static void app_unset_and_cleanup(void *obj)
-{
- struct stasis_app *app = obj;
- if (obj) {
- app_set_is_in_app_stasis(app, 0);
- ao2_cleanup(obj);
+ * \brief In addition to running ao2_cleanup(), this function also removes the
+ * object from the stasis_controls() container.
+ */
+static void control_unlink(struct stasis_app_control *control)
+{
+ RAII_VAR(struct ao2_container *, controls, NULL, ao2_cleanup);
+
+ if (control) {
+ controls = stasis_contols();
+ ao2_unlink_flags(controls, control, OBJ_POINTER | OBJ_UNLINK | OBJ_NODATA);
+ ao2_cleanup(control);
}
}
@@ -340,7 +364,8 @@
static int stasis_exec(struct ast_channel *chan, const char *data)
{
RAII_VAR(struct ao2_container *, apps, stasis_apps(), ao2_cleanup);
- RAII_VAR(struct stasis_app *, app, NULL, app_unset_and_cleanup);
+ RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_app_control *, control, NULL, control_unlink);
RAII_VAR(struct stasis_subscription *, subscription, NULL, stasis_unsubscribe);
int res = 0;
char *parse = NULL;
@@ -364,16 +389,24 @@
}
app = ao2_find(apps, args.app_name, OBJ_KEY);
-
if (!app) {
ast_log(LOG_ERROR, "Stasis app '%s' not registered\n", args.app_name);
return -1;
}
- app_set_is_in_app_stasis(app, 1);
+ {
+ RAII_VAR(struct ao2_container *, controls, NULL, ao2_cleanup);
+
+ controls = stasis_contols();
+ control = control_create(ast_channel_uniqueid(chan));
+ if (!control) {
+ ast_log(LOG_ERROR, "Allocated failed\n");
+ return -1;
+ }
+ ao2_link(controls, control);
+ }
subscription = stasis_subscribe(ast_channel_events(chan), sub_handler, app);
-
if (subscription == NULL) {
ast_log(LOG_ERROR, "Error subscribing app %s to channel %s\n", args.app_name, ast_channel_name(chan));
return -1;
@@ -385,7 +418,7 @@
return res;
}
- while (!hungup && !app_continue_test_and_reset(app) && ast_waitfor(chan, -1) > -1) {
+ while (!hungup && !control_continue_test_and_reset(control) && ast_waitfor(chan, -1) > -1) {
RAII_VAR(struct ast_frame *, f, ast_read(chan), ast_frame_dtor);
if (!f) {
ast_debug(3, "%s: No more frames. Must be done, I guess.\n", ast_channel_uniqueid(chan));
@@ -480,6 +513,11 @@
return AST_MODULE_LOAD_FAILURE;
}
+ __stasis_controls = ao2_container_alloc(CONTROLS_NUM_BUCKETS, app_hash, app_compare);
+ if (__stasis_controls == NULL) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
r |= ast_register_application_xml(stasis, stasis_exec);
return r;
}
@@ -490,6 +528,9 @@
ao2_cleanup(__stasis_apps);
__stasis_apps = NULL;
+
+ ao2_cleanup(__stasis_controls);
+ __stasis_controls = NULL;
r |= ast_unregister_application(stasis);
return r;
Modified: team/dlee/stasis-app/include/asterisk/app_stasis.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/include/asterisk/app_stasis.h?view=diff&rev=381838&r1=381837&r2=381838
==============================================================================
--- team/dlee/stasis-app/include/asterisk/app_stasis.h (original)
+++ team/dlee/stasis-app/include/asterisk/app_stasis.h Wed Feb 20 14:23:46 2013
@@ -32,7 +32,9 @@
#include "asterisk/channel.h"
#include "asterisk/json.h"
-/*! \brief Handler for controlling app_stasis */
+/*! @{ */
+
+/*! \brief Handler for a registered Stasis applicatoin. */
struct stasis_app;
/*!
@@ -47,23 +49,6 @@
* \return -1 for error.
*/
int stasis_app_send(const char *app_name, struct ast_json *message);
-
-/*!
- * \brief Returns the handler for the given channel
- * \param chan Channel to handle.
- * \return NULL channel not in Stasis application
- * \return Pointer to app_stasis handler.
- */
-struct stasis_app *stasis_app_find_by_channel(struct ast_channel *chan);
-
-/*!
- * \brief Exit \c app_stasis and continue execution in the dialplan.
- *
- * If the channel is no longer in \c app_stasis, this function does nothing.
- *
- * \param handler Handler for \c app_stasis
- */
-void stasis_app_continue(struct stasis_app *handler);
/*!
* \brief Callback for Stasis application handler.
@@ -95,6 +80,34 @@
*/
void stasis_app_unregister(const char *app_name);
+/*! @} */
+
+/*! @{ */
+
+/*! \brief Handler for controlling a channel that's in a Stasis application */
+struct stasis_app_control;
+
+/*!
+ * \brief Returns the handler for the given channel
+ * \param chan Channel to handle.
+ * \return NULL channel not in Stasis application
+ * \return Pointer to app_stasis handler.
+ */
+struct stasis_app_control *stasis_app_control_find_by_channel(const struct ast_channel *chan);
+
+/*!
+ * \brief Exit \c app_stasis and continue execution in the dialplan.
+ *
+ * If the channel is no longer in \c app_stasis, this function does nothing.
+ *
+ * \param handler Handler for \c app_stasis
+ */
+void stasis_app_control_continue(struct stasis_app_control *handler);
+
+/*! @} */
+
+/*! @{ */
+
/*!
* \brief Build a JSON object from a \ref ast_channel_snapshot.
* \return JSON object representing channel snapshot.
@@ -112,4 +125,6 @@
*/
struct ast_json *stasis_app_event_create(const char *event_name, const struct ast_channel_snapshot *channel_info, const struct ast_json *extra_info);
+/*! @} */
+
#endif /* _ASTERISK_APP_STASIS_H */
More information about the asterisk-commits
mailing list