[asterisk-commits] mmichelson: branch group/CCSS r224441 - in /team/group/CCSS: include/asterisk...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Oct 18 16:23:35 CDT 2009
Author: mmichelson
Date: Sun Oct 18 16:23:32 2009
New Revision: 224441
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=224441
Log:
Make the cc_interface, cc_interface_tree, and cc_tree_item
private to ccss.c
Modified:
team/group/CCSS/include/asterisk/ccss.h
team/group/CCSS/main/ccss.c
Modified: team/group/CCSS/include/asterisk/ccss.h
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/include/asterisk/ccss.h?view=diff&rev=224441&r1=224440&r2=224441
==============================================================================
--- team/group/CCSS/include/asterisk/ccss.h (original)
+++ team/group/CCSS/include/asterisk/ccss.h Sun Oct 18 16:23:32 2009
@@ -500,54 +500,6 @@
char name[1];
};
-/*!
- * \brief An item in a CC interface tree.
- *
- * These are the individual items in an interface tree.
- * The key difference between this structure and the ast_cc_interface
- * is that this structure contains data which is intrinsic to the item's
- * placement in the tree, such as who its parent is.
- */
-struct ast_cc_tree_item {
- /* Information regarding the interface.
- */
- struct ast_cc_interface *interface;
- /* Every interface has an id associated with it. Think of
- * it like a "primary key"
- */
- unsigned int id;
- /* Who is this interface's parent interface? The "root" of
- * the tree will have 0 for this. Everyone else will have at
- * least 1 as their parent_id.
- */
- unsigned int parent_id;
- /* What service was offered by the endpoint. Note that
- * this field is completely irrelevant for ast_cc_tree_items
- * representing dialplan extensions.
- */
- enum ast_cc_service_type service_offered;
- /*!
- * Name that should be used to recall specified interface
- *
- * When issuing a CC recall, some technologies will require
- * that a name other than the device name is dialed. For instance,
- * with SIP, a specific URI will be used which chan_sip will be able
- * to recognize as being a CC recall. Similarly, ISDN will need a specific
- * dial string to know that the call is a recall.
- */
- char *dialable_name;
- AST_LIST_ENTRY(ast_cc_tree_item) next;
-};
-
-/*!
- * \brief The "tree" of interfaces that is dialed.
- *
- * It is reference counted since several threads may need
- * to use it, and it may last beyond the lifetime of a single
- * thread.
- */
-AST_LIST_HEAD(ast_cc_interface_tree, ast_cc_tree_item);
-
/* END TREE STRUCTURES AND API FOR APP_DIAL'S USE */
/*!
Modified: team/group/CCSS/main/ccss.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/main/ccss.c?view=diff&rev=224441&r1=224440&r2=224441
==============================================================================
--- team/group/CCSS/main/ccss.c (original)
+++ team/group/CCSS/main/ccss.c Sun Oct 18 16:23:32 2009
@@ -617,221 +617,6 @@
#define cc_ref(obj, debug) ({ao2_t_ref((obj), +1, (debug)); (obj);})
#define cc_unref(obj, debug) ({ao2_t_ref((obj), -1, (debug)); NULL;})
-
-/* Generic agent callbacks */
-static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan);
-static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent);
-static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent);
-static void cc_generic_agent_ack(struct ast_cc_agent *agent);
-static enum ast_device_state cc_generic_agent_status_request(struct ast_cc_agent *agent);
-static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent);
-static int cc_generic_agent_stop_monitoring(struct ast_cc_agent *agent);
-static int cc_generic_agent_recall(struct ast_cc_agent *agent);
-static void cc_generic_agent_destructor(struct ast_cc_agent *agent);
-
-static struct ast_cc_agent_callbacks generic_agent_callbacks = {
- .type = "generic",
- .init = cc_generic_agent_init,
- .start_offer_timer = cc_generic_agent_start_offer_timer,
- .stop_offer_timer = cc_generic_agent_stop_offer_timer,
- .ack = cc_generic_agent_ack,
- .status_request = cc_generic_agent_status_request,
- .start_monitoring = cc_generic_agent_start_monitoring,
- .stop_monitoring = cc_generic_agent_stop_monitoring,
- .recall = cc_generic_agent_recall,
- .destructor = cc_generic_agent_destructor,
-};
-
-struct cc_generic_agent_pvt {
- /*!
- * Subscription to device state
- *
- * Used in the CC_CALLER_BUSY state. The
- * generic agent will subscribe to the
- * device state of the caller in order to
- * determine when we may move on
- */
- struct ast_event_sub *sub;
- /*!
- * Scheduler id of offer timer.
- */
- int offer_timer_id;
-};
-
-static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
-{
- struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
-
- if (!generic_pvt) {
- return -1;
- }
-
- generic_pvt->offer_timer_id = -1;
- agent->private_data = generic_pvt;
- ast_set_flag(agent, AST_CC_AGENT_SKIP_OFFER);
- return 0;
-}
-
-static int offer_timer_expire(const void *data)
-{
- const struct ast_cc_agent *agent = data;
- struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
- ast_log(LOG_NOTICE, "Queuing change request because offer timer has expired.\n");
- agent_pvt->offer_timer_id = -1;
- ast_cc_request_state_change(CC_FAILED, agent->core_id, "Generic agent offer timer expired");
- return 0;
-}
-
-static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent)
-{
- int when;
- int sched_id;
- struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
-
- ast_assert(cc_sched_thread != NULL);
- ast_assert(agent->cc_params != NULL);
-
- when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
- ast_log(LOG_NOTICE, "About to schedule timer expiration for %d ms\n", when);
- if ((sched_id = ast_sched_thread_add(cc_sched_thread, when, offer_timer_expire, agent)) == -1) {
- return -1;
- }
- generic_pvt->offer_timer_id = sched_id;
- return 0;
-}
-
-static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
-{
- struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
-
- if (generic_pvt->offer_timer_id != -1) {
- ast_sched_thread_del(cc_sched_thread, generic_pvt->offer_timer_id);
- generic_pvt->offer_timer_id = -1;
- }
- return 0;
-}
-
-static void cc_generic_agent_ack(struct ast_cc_agent *agent)
-{
- /* The generic agent doesn't have to do anything special to
- * acknowledge a CC request. Just return.
- */
- return;
-}
-
-static enum ast_device_state cc_generic_agent_status_request(struct ast_cc_agent *agent)
-{
- return ast_device_state(agent->interface);
-}
-
-static void generic_devstate_cb(const struct ast_event *event, void *userdata)
-{
- struct ast_cc_agent *agent = userdata;
- struct ast_str *str = ast_str_alloca(128);
- ast_str_set(&str, 0, "%s is no longer busy\n", agent->interface);
- ast_cc_request_state_change(CC_ACTIVE, agent->core_id, ast_str_buffer(str));
-}
-
-static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent)
-{
- struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
- struct ast_str *str = ast_str_alloca(128);
-
- ast_assert(generic_pvt->sub == NULL);
- ast_str_set(&str, 0, "Starting to monitor %s device state since it is busy\n", agent->interface);
-
- if (!(generic_pvt->sub = ast_event_subscribe(
- AST_EVENT_DEVICE_STATE, generic_devstate_cb, ast_str_buffer(str), agent,
- AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, agent->interface,
- AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, AST_DEVICE_NOT_INUSE,
- AST_EVENT_IE_END))) {
- return -1;
- }
- return 0;
-}
-
-static int cc_generic_agent_stop_monitoring(struct ast_cc_agent *agent)
-{
- struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
-
- ast_assert(generic_pvt->sub != NULL);
-
- generic_pvt->sub = ast_event_unsubscribe(generic_pvt->sub);
- return 0;
-}
-
-static void *generic_recall(void *data)
-{
- struct ast_cc_agent *agent = data;
- char *interface = ast_strdupa(agent->interface);
- char *tech;
- char *target;
- int reason;
- struct ast_channel *chan;
- struct ast_cc_tree_item *tree_item = AST_LIST_FIRST(agent->interface_tree);
- char *full_extension = ast_strdupa(tree_item->interface->name);
- char *context;
- char *exten;
- const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
- tech = interface;
- if ((target = strchr(interface, '/'))) {
- *target++ = '\0';
- }
- if (!(chan = ast_request_and_dial(tech, AST_FORMAT_SLINEAR, NULL, target, 20000, &reason, NULL, NULL))) {
- /* Hmm, no channel. Sucks for you, bud.
- */
- ast_log(LOG_NOTICE, "Failed to call back %s for reason %d\n", agent->interface, reason);
- ast_cc_request_state_change(CC_FAILED, agent->core_id, "Failed to call back interface\n");
- return NULL;
- }
- if (!ast_strlen_zero(callback_macro)) {
- ast_log(LOG_NOTICE, "There's a callback macro configured\n");
- if (ast_app_run_macro(NULL, chan, callback_macro, NULL)) {
- ast_cc_request_state_change(CC_FAILED, agent->core_id, "Callback macro failed. Maybe a hangup?");
- ast_hangup(chan);
- return NULL;
- }
- }
- /* We have a channel. It's time now to set up the datastore of recalled CC interfaces.
- * This will be a common task for all recall functions. If it were possible, I'd have
- * the core do it automatically, but alas I cannot. Instead, I will provide a public
- * function to do so.
- */
- ast_setup_cc_recall_datastore(chan, agent);
- ast_set_cc_interfaces_chanvar(chan, full_extension);
- /* Now we can bust apart the outbound name so that the PBX will run. */
- exten = full_extension;
- if ((context = strchr(full_extension, '@'))) {
- *context++ = '\0';
- }
- ast_copy_string(chan->exten, exten, sizeof(chan->exten));
- ast_copy_string(chan->context, context, sizeof(chan->context));
- chan->priority = 1;
- ast_pbx_start(chan);
- return NULL;
-}
-
-static int cc_generic_agent_recall(struct ast_cc_agent *agent)
-{
- pthread_t clotho;
- ast_pthread_create_detached_background(&clotho, NULL, generic_recall, agent);
- return 0;
-}
-
-static void cc_generic_agent_destructor(struct ast_cc_agent *agent)
-{
- struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
- if (!agent_pvt) {
- return;
- }
-
- if (agent_pvt->sub) {
- agent_pvt->sub = ast_event_unsubscribe(agent_pvt->sub);
- }
-
- ast_free(agent_pvt);
-}
-
static void destroy_link(struct ast_cc_monitor_link *link)
{
ast_log(LOG_NOTICE, "Destroying link with parent %s and child %s\n",
@@ -1255,14 +1040,54 @@
ast_free(gen_mon_pvt);
return;
}
-#if 0
-static int print_debug(void *obj, void *args, int flags)
-{
- struct ast_cc_monitor *monitor = obj;
- ast_log(LOG_NOTICE, "%s is in the container\n", monitor->interface->name);
- return 0;
-}
-#endif
+
+/*!
+ * \brief An item in a CC interface tree.
+ *
+ * These are the individual items in an interface tree.
+ * The key difference between this structure and the ast_cc_interface
+ * is that this structure contains data which is intrinsic to the item's
+ * placement in the tree, such as who its parent is.
+ */
+struct cc_tree_item {
+ /* Information regarding the interface.
+ */
+ struct ast_cc_interface *interface;
+ /* Every interface has an id associated with it. Think of
+ * it like a "primary key"
+ */
+ unsigned int id;
+ /* Who is this interface's parent interface? The "root" of
+ * the tree will have 0 for this. Everyone else will have at
+ * least 1 as their parent_id.
+ */
+ unsigned int parent_id;
+ /* What service was offered by the endpoint. Note that
+ * this field is completely irrelevant for cc_tree_items
+ * representing dialplan extensions.
+ */
+ enum ast_cc_service_type service_offered;
+ /*!
+ * Name that should be used to recall specified interface
+ *
+ * When issuing a CC recall, some technologies will require
+ * that a name other than the device name is dialed. For instance,
+ * with SIP, a specific URI will be used which chan_sip will be able
+ * to recognize as being a CC recall. Similarly, ISDN will need a specific
+ * dial string to know that the call is a recall.
+ */
+ char *dialable_name;
+ AST_LIST_ENTRY(cc_tree_item) next;
+};
+
+/*!
+ * \brief The "tree" of interfaces that is dialed.
+ *
+ * It is reference counted since several threads may need
+ * to use it, and it may last beyond the lifetime of a single
+ * thread.
+ */
+AST_LIST_HEAD(ast_cc_interface_tree, cc_tree_item);
static void cc_interface_destroy(void *data)
{
@@ -1271,7 +1096,7 @@
ast_cc_config_params_destroy(interface->config_params);
}
-static void cc_tree_item_destroy(struct ast_cc_tree_item *tree_item)
+static void cc_tree_item_destroy(struct cc_tree_item *tree_item)
{
cc_unref(tree_item->interface, "Unreffing tree's reference to interface");
ast_free(tree_item->dialable_name);
@@ -1281,7 +1106,7 @@
static void cc_interface_tree_destroy(void *data)
{
struct ast_cc_interface_tree *cc_interface_tree = data;
- struct ast_cc_tree_item *tree_item;
+ struct cc_tree_item *tree_item;
while ((tree_item = AST_LIST_REMOVE_HEAD(cc_interface_tree, next))) {
cc_tree_item_destroy(tree_item);
}
@@ -1306,12 +1131,12 @@
* This value serves a dual-purpose. When dial starts, if the
* dialed_cc_interfaces datastore currently exists on the calling
* channel, then the dial_parent_id will serve as a means of
- * letting the new extension ast_cc_tree_item we create know
+ * letting the new extension cc_tree_item we create know
* who his parent is. This value will be the extension
- * ast_cc_tree_item that dialed the local channel that resulted
+ * cc_tree_item that dialed the local channel that resulted
* in the new Dial app being called.
*
- * In addition, once an extension ast_cc_tree_item is created,
+ * In addition, once an extension cc_tree_item is created,
* the dial_parent_id will be changed to the id of that newly
* created interface. This way, device interfaces created from
* receiving AST_CONTROL_CC frames can use this field to determine
@@ -1456,19 +1281,19 @@
*
* When app_dial starts, this function is called in order to set up the
* information about the extension in which this Dial is occurring. Any
- * devices dialed will have this particular ast_cc_tree_item as a parent.
+ * devices dialed will have this particular cc_tree_item as a parent.
*
* \param exten Extension from which Dial is occurring
* \param context Context to which exten belongs
* \param parent_id What should we set the parent_id of this interface to?
* \retval NULL Memory allocation failure
- * \retval non-NULL The newly-created ast_cc_tree_item for the extension
+ * \retval non-NULL The newly-created cc_tree_item for the extension
*/
-static struct ast_cc_tree_item *cc_extension_tree_item_init(const char * const exten, const char * const context, const unsigned int parent_id)
+static struct cc_tree_item *cc_extension_tree_item_init(const char * const exten, const char * const context, const unsigned int parent_id)
{
struct ast_str *str = ast_str_alloca(2 * AST_MAX_EXTENSION);
struct ast_cc_interface *cc_interface;
- struct ast_cc_tree_item *tree_item;
+ struct cc_tree_item *tree_item;
ast_str_set(&str, 0, "%s@%s", exten, context);
@@ -1508,7 +1333,7 @@
*/
static int cc_interfaces_datastore_init(struct ast_channel *chan) {
struct dialed_cc_interfaces *interfaces;
- struct ast_cc_tree_item *tree_item;
+ struct cc_tree_item *tree_item;
struct ast_datastore *dial_cc_datastore;
/*XXX This may be a bit controversial. In an attempt to not allocate
@@ -1559,7 +1384,7 @@
}
/*!
- * \brief Allocate and intitialize a device ast_cc_tree_item
+ * \brief Allocate and intitialize a device cc_tree_item
*
* For all intents and purposes, this is the same as
* cc_extension_tree_item_init, except that there is only
@@ -1581,10 +1406,10 @@
* \retval NULL Memory allocation failure
* \retval non-NULL The new ast_cc_interface created.
*/
-static struct ast_cc_tree_item *cc_device_tree_item_init(const char * const name, const int parent_id, const struct ast_control_cc_payload *cc_data)
+static struct cc_tree_item *cc_device_tree_item_init(const char * const name, const int parent_id, const struct ast_control_cc_payload *cc_data)
{
struct ast_cc_interface *cc_interface;
- struct ast_cc_tree_item *tree_item;
+ struct cc_tree_item *tree_item;
size_t name_len = strlen(name);
if (!(cc_interface = ao2_alloc(sizeof(*cc_interface) + name_len, cc_interface_destroy))) {
@@ -1621,7 +1446,7 @@
* from an outbound channel.
*
* This function will call cc_device_tree_item_init to
- * create the new ast_cc_tree_item for the device from which
+ * create the new cc_tree_item for the device from which
* we read the frame. In addition, the new device will be added
* to the interface tree on the dialed_cc_interfaces datastore
* on the inbound channel.
@@ -1639,7 +1464,7 @@
{
char device_name[AST_CHANNEL_NAME];
char *dash;
- struct ast_cc_tree_item *tree_item;
+ struct cc_tree_item *tree_item;
struct ast_datastore *cc_datastore;
struct dialed_cc_interfaces *cc_interfaces;
struct ast_control_cc_payload *cc_data = frame_data;
@@ -1749,7 +1574,7 @@
struct ast_datastore *cc_interfaces_datastore;
struct dialed_cc_interfaces *interfaces;
- struct ast_cc_tree_item *tree_item;
+ struct cc_tree_item *tree_item;
ast_channel_lock(chan);
if (ast_get_cc_agent_policy(ast_channel_get_cc_config_params(chan)) == AST_CC_AGENT_NEVER) {
@@ -1881,6 +1706,221 @@
ast_cc_config_params_destroy(agent->cc_params);
ast_free(agent);
}
+
+/* Generic agent callbacks */
+static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan);
+static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent);
+static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent);
+static void cc_generic_agent_ack(struct ast_cc_agent *agent);
+static enum ast_device_state cc_generic_agent_status_request(struct ast_cc_agent *agent);
+static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent);
+static int cc_generic_agent_stop_monitoring(struct ast_cc_agent *agent);
+static int cc_generic_agent_recall(struct ast_cc_agent *agent);
+static void cc_generic_agent_destructor(struct ast_cc_agent *agent);
+
+static struct ast_cc_agent_callbacks generic_agent_callbacks = {
+ .type = "generic",
+ .init = cc_generic_agent_init,
+ .start_offer_timer = cc_generic_agent_start_offer_timer,
+ .stop_offer_timer = cc_generic_agent_stop_offer_timer,
+ .ack = cc_generic_agent_ack,
+ .status_request = cc_generic_agent_status_request,
+ .start_monitoring = cc_generic_agent_start_monitoring,
+ .stop_monitoring = cc_generic_agent_stop_monitoring,
+ .recall = cc_generic_agent_recall,
+ .destructor = cc_generic_agent_destructor,
+};
+
+struct cc_generic_agent_pvt {
+ /*!
+ * Subscription to device state
+ *
+ * Used in the CC_CALLER_BUSY state. The
+ * generic agent will subscribe to the
+ * device state of the caller in order to
+ * determine when we may move on
+ */
+ struct ast_event_sub *sub;
+ /*!
+ * Scheduler id of offer timer.
+ */
+ int offer_timer_id;
+};
+
+static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
+{
+ struct cc_generic_agent_pvt *generic_pvt = ast_calloc(1, sizeof(*generic_pvt));
+
+ if (!generic_pvt) {
+ return -1;
+ }
+
+ generic_pvt->offer_timer_id = -1;
+ agent->private_data = generic_pvt;
+ ast_set_flag(agent, AST_CC_AGENT_SKIP_OFFER);
+ return 0;
+}
+
+static int offer_timer_expire(const void *data)
+{
+ const struct ast_cc_agent *agent = data;
+ struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
+ ast_log(LOG_NOTICE, "Queuing change request because offer timer has expired.\n");
+ agent_pvt->offer_timer_id = -1;
+ ast_cc_request_state_change(CC_FAILED, agent->core_id, "Generic agent offer timer expired");
+ return 0;
+}
+
+static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent)
+{
+ int when;
+ int sched_id;
+ struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
+
+ ast_assert(cc_sched_thread != NULL);
+ ast_assert(agent->cc_params != NULL);
+
+ when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
+ ast_log(LOG_NOTICE, "About to schedule timer expiration for %d ms\n", when);
+ if ((sched_id = ast_sched_thread_add(cc_sched_thread, when, offer_timer_expire, agent)) == -1) {
+ return -1;
+ }
+ generic_pvt->offer_timer_id = sched_id;
+ return 0;
+}
+
+static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
+{
+ struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
+
+ if (generic_pvt->offer_timer_id != -1) {
+ ast_sched_thread_del(cc_sched_thread, generic_pvt->offer_timer_id);
+ generic_pvt->offer_timer_id = -1;
+ }
+ return 0;
+}
+
+static void cc_generic_agent_ack(struct ast_cc_agent *agent)
+{
+ /* The generic agent doesn't have to do anything special to
+ * acknowledge a CC request. Just return.
+ */
+ return;
+}
+
+static enum ast_device_state cc_generic_agent_status_request(struct ast_cc_agent *agent)
+{
+ return ast_device_state(agent->interface);
+}
+
+static void generic_devstate_cb(const struct ast_event *event, void *userdata)
+{
+ struct ast_cc_agent *agent = userdata;
+ struct ast_str *str = ast_str_alloca(128);
+ ast_str_set(&str, 0, "%s is no longer busy\n", agent->interface);
+ ast_cc_request_state_change(CC_ACTIVE, agent->core_id, ast_str_buffer(str));
+}
+
+static int cc_generic_agent_start_monitoring(struct ast_cc_agent *agent)
+{
+ struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
+ struct ast_str *str = ast_str_alloca(128);
+
+ ast_assert(generic_pvt->sub == NULL);
+ ast_str_set(&str, 0, "Starting to monitor %s device state since it is busy\n", agent->interface);
+
+ if (!(generic_pvt->sub = ast_event_subscribe(
+ AST_EVENT_DEVICE_STATE, generic_devstate_cb, ast_str_buffer(str), agent,
+ AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, agent->interface,
+ AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, AST_DEVICE_NOT_INUSE,
+ AST_EVENT_IE_END))) {
+ return -1;
+ }
+ return 0;
+}
+
+static int cc_generic_agent_stop_monitoring(struct ast_cc_agent *agent)
+{
+ struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
+
+ ast_assert(generic_pvt->sub != NULL);
+
+ generic_pvt->sub = ast_event_unsubscribe(generic_pvt->sub);
+ return 0;
+}
+
+static void *generic_recall(void *data)
+{
+ struct ast_cc_agent *agent = data;
+ char *interface = ast_strdupa(agent->interface);
+ char *tech;
+ char *target;
+ int reason;
+ struct ast_channel *chan;
+ struct cc_tree_item *tree_item = AST_LIST_FIRST(agent->interface_tree);
+ char *full_extension = ast_strdupa(tree_item->interface->name);
+ char *context;
+ char *exten;
+ const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
+ tech = interface;
+ if ((target = strchr(interface, '/'))) {
+ *target++ = '\0';
+ }
+ if (!(chan = ast_request_and_dial(tech, AST_FORMAT_SLINEAR, NULL, target, 20000, &reason, NULL, NULL))) {
+ /* Hmm, no channel. Sucks for you, bud.
+ */
+ ast_log(LOG_NOTICE, "Failed to call back %s for reason %d\n", agent->interface, reason);
+ ast_cc_request_state_change(CC_FAILED, agent->core_id, "Failed to call back interface\n");
+ return NULL;
+ }
+ if (!ast_strlen_zero(callback_macro)) {
+ ast_log(LOG_NOTICE, "There's a callback macro configured\n");
+ if (ast_app_run_macro(NULL, chan, callback_macro, NULL)) {
+ ast_cc_request_state_change(CC_FAILED, agent->core_id, "Callback macro failed. Maybe a hangup?");
+ ast_hangup(chan);
+ return NULL;
+ }
+ }
+ /* We have a channel. It's time now to set up the datastore of recalled CC interfaces.
+ * This will be a common task for all recall functions. If it were possible, I'd have
+ * the core do it automatically, but alas I cannot. Instead, I will provide a public
+ * function to do so.
+ */
+ ast_setup_cc_recall_datastore(chan, agent);
+ ast_set_cc_interfaces_chanvar(chan, full_extension);
+ /* Now we can bust apart the outbound name so that the PBX will run. */
+ exten = full_extension;
+ if ((context = strchr(full_extension, '@'))) {
+ *context++ = '\0';
+ }
+ ast_copy_string(chan->exten, exten, sizeof(chan->exten));
+ ast_copy_string(chan->context, context, sizeof(chan->context));
+ chan->priority = 1;
+ ast_pbx_start(chan);
+ return NULL;
+}
+
+static int cc_generic_agent_recall(struct ast_cc_agent *agent)
+{
+ pthread_t clotho;
+ ast_pthread_create_detached_background(&clotho, NULL, generic_recall, agent);
+ return 0;
+}
+
+static void cc_generic_agent_destructor(struct ast_cc_agent *agent)
+{
+ struct cc_generic_agent_pvt *agent_pvt = agent->private_data;
+ if (!agent_pvt) {
+ return;
+ }
+
+ if (agent_pvt->sub) {
+ agent_pvt->sub = ast_event_unsubscribe(agent_pvt->sub);
+ }
+
+ ast_free(agent_pvt);
+}
+
static void cc_core_instance_destructor(void *data)
{
@@ -2009,7 +2049,7 @@
return ao2_t_find(cc_monitors, &finder, OBJ_POINTER, "Trying to find specific monitor");
}
-static struct ast_cc_monitor *find_or_create_monitor(struct ast_cc_monitor *parent, struct ast_cc_tree_item *tree_item, const int core_id)
+static struct ast_cc_monitor *find_or_create_monitor(struct ast_cc_monitor *parent, struct cc_tree_item *tree_item, const int core_id)
{
struct ast_cc_monitor *new_monitor;
struct ast_cc_monitor_link *new_link;
@@ -2039,9 +2079,9 @@
return new_monitor;
}
-static void interface_tree_to_monitor(struct ast_cc_tree_item *current_place, struct ast_cc_monitor *parent, const int core_id)
-{
- struct ast_cc_tree_item *tree_item = current_place;
+static void interface_tree_to_monitor(struct cc_tree_item *current_place, struct ast_cc_monitor *parent, const int core_id)
+{
+ struct cc_tree_item *tree_item = current_place;
struct ast_cc_monitor *monitor = find_or_create_monitor(parent, current_place, core_id);
if (!monitor) {
@@ -2520,7 +2560,7 @@
{
struct ast_datastore *recall_datastore;
struct ast_cc_interface_tree *interface_tree;
- struct ast_cc_tree_item *tree_item_iter;
+ struct cc_tree_item *tree_item_iter;
struct cc_recall_ds_data *recall_data;
unsigned int exten_id = 0;
struct ast_str *var_value = ast_str_create(64);
More information about the asterisk-commits
mailing list