[asterisk-commits] mmichelson: branch mmichelson/queue_bugbug r394458 - in /team/mmichelson/queu...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jul 16 12:01:16 CDT 2013


Author: mmichelson
Date: Tue Jul 16 12:01:15 2013
New Revision: 394458

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=394458
Log:
Get up to date so I have app_agent_pool.c 


Added:
    team/mmichelson/queue_bugbug/apps/app_agent_pool.c
      - copied unchanged from r394442, trunk/apps/app_agent_pool.c
Removed:
    team/mmichelson/queue_bugbug/channels/chan_agent.c
Modified:
    team/mmichelson/queue_bugbug/   (props changed)
    team/mmichelson/queue_bugbug/CHANGES
    team/mmichelson/queue_bugbug/UPGRADE.txt
    team/mmichelson/queue_bugbug/configs/agents.conf.sample
    team/mmichelson/queue_bugbug/configs/queues.conf.sample
    team/mmichelson/queue_bugbug/include/asterisk/bridging.h
    team/mmichelson/queue_bugbug/include/asterisk/config_options.h
    team/mmichelson/queue_bugbug/include/asterisk/stasis_channels.h
    team/mmichelson/queue_bugbug/main/bridging.c
    team/mmichelson/queue_bugbug/main/stasis_channels.c
    team/mmichelson/queue_bugbug/res/res_http_websocket.c
    team/mmichelson/queue_bugbug/res/res_stasis_http.c

Propchange: team/mmichelson/queue_bugbug/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Jul 16 12:01:15 2013
@@ -1,1 +1,1 @@
-/trunk:1-394370
+/trunk:1-394457

Modified: team/mmichelson/queue_bugbug/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/CHANGES?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/CHANGES (original)
+++ team/mmichelson/queue_bugbug/CHANGES Tue Jul 16 12:01:15 2013
@@ -14,10 +14,17 @@
 Applications
 ------------------
 
+AgentLogin
+------------------
+ * The application no longer does agent authentication.  The dialplan needs to
+   perform this function before running AgentLogin.  If the agent is already
+   logged in, dialplan will continue with the AGENT_STATUS channel variable
+   set to ALREADY_LOGGED_IN.
+
 AgentMonitorOutgoing
 ------------------
- * The 'c' option has been removed. It is not possible to modify the name of a
-   channel involved in a CDR.
+ * Application removed.  It was a holdover from when AgentCallbackLogin was
+   removed.
 
 ForkCDR
 ------------------
@@ -260,8 +267,8 @@
    of "CallerID" and "ConnectedID" to avoid confusion with similarly named
    parameters in the channel snapshot.
 
- * The "Agentlogin" and "Agentlogoff" events have been renamed "AgentLogin" and
-   "AgentLogoff" respectively.
+ * The AMI events "Agentlogin" and "Agentlogoff" have been renamed
+   "AgentLogin" and "AgentLogoff" respectively.
 
  * The "Channel" key used in the "AlarmClear", "Alarm", and "DNDState" has been
    renamed "DAHDIChannel" since it does not convey an Asterisk channel name.
@@ -453,6 +460,21 @@
    and pretending otherwise helps no one.
  * The AGENTUPDATECDR channel variable has also been removed, for the same
    reason as the updatecdr option.
+ * The driver is no longer a Data retrieval API data provider for the
+   AMI DataGet action.
+ * The endcall and enddtmf configuration options are removed.  Use the
+   dialplan function CHANNEL(dtmf-features) to set DTMF features on the agent
+   channel before calling AgentLogin.
+ * chan_agent is removed and replaced with AgentLogin and AgentRequest dialplan
+   applications.  Agents are connected with callers using the new AgentRequest
+   dialplan application.  The Agents:<agent-id> device state is available to
+   monitor the status of an agent.  See agents.conf.sample for valid
+   configuration options.
+
+chan_bridge
+------------------
+ * chan_bridge is removed and its functionality is incorporated into ConfBridge
+   itself.
 
 chan_local
 ------------------

Modified: team/mmichelson/queue_bugbug/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/UPGRADE.txt?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/UPGRADE.txt (original)
+++ team/mmichelson/queue_bugbug/UPGRADE.txt Tue Jul 16 12:01:15 2013
@@ -22,8 +22,8 @@
 ===========================================================
 
 AgentMonitorOutgoing
- - The 'c' option has been removed. It is not possible to modify the name of a
-   channel involved in a CDR.
+ - Application removed.  It was a holdover from when AgentCallbackLogin was
+   removed.
 
 NoCDR:
  - This application is deprecated. Please use the CDR_PROP function instead.
@@ -140,6 +140,15 @@
    and pretending otherwise helps no one.
  - The AGENTUPDATECDR channel variable has also been removed, for the same
    reason as the updatecdr option.
+ - chan_agent is removed and replaced with AgentLogin and AgentRequest dialplan
+   applications.  Agents are connected with callers using the new AgentRequest
+   dialplan application.  The Agents:<agent-id> device state is available to
+   monitor the status of an agent.  See agents.conf.sample for valid
+   configuration options.
+
+chan_bridge
+ - chan_bridge is removed and its functionality is incorporated into ConfBridge
+   itself.
 
 chan_dahdi:
  - Analog port dialing and deferred DTMF dialing for PRI now distinguishes

Modified: team/mmichelson/queue_bugbug/configs/agents.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/configs/agents.conf.sample?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/configs/agents.conf.sample (original)
+++ team/mmichelson/queue_bugbug/configs/agents.conf.sample Tue Jul 16 12:01:15 2013
@@ -1,102 +1,70 @@
 ;
-; Agent configuration
+; Agent pool configuration
 ;
 
 [general]
+; The general section of this config is not currently used, but reserved
+; for future use.
 
-[agents]
+;[agent-id]
+; Define ackcall to require the agent to give a DTMF acknowledgement
+; when the agent receives a call.
+; The channel variable AGENTACKCALL overrides on agent login.
+; Default is "no".
+;ackcall=no
 ;
-; Define maxlogintries to allow agent to try max logins before
-; failed.
-; default to 3
+; Set what DTMF key sequence the agent should use to acknowledge a call.
+; The channel variable AGENTACCEPTDTMF overrides on agent login.
+; This option is ignored unless ackcall is enabled.
+; Default is "#".
+;acceptdtmf=##
 ;
-;maxlogintries=5
-;
-;
-; Define autologoff times if appropriate.  This is how long
-; the phone has to ring with no answer before the agent is
-; automatically logged off (in seconds)
-;
+; Set how many seconds a call for the agent has to wait for the agent to
+; acknowledge the call before the agent is automatically logged off.  If
+; set to zero then the call will wait forever for the agent to acknowledge.
+; The channel variable AGENTAUTOLOGOFF overrides on agent login.
+; This option is ignored unless ackcall is enabled.
+; Default is 0.
 ;autologoff=15
 ;
-; Define autologoffunavail to have agents automatically logged
-; out when the extension that they are at returns a CHANUNAVAIL
-; status when a call is attempted to be sent there.
-; Default is "no".
-;
-;autologoffunavail=yes
-;
-; Define ackcall to require a DTMF acknowledgement when
-; a logged-in agent receives a call.  Default is "no".
-; Use the acceptdtmf option to configure what DTMF key
-; press should be used to acknowledge the call. The
-; default is '#'.
-;
-;ackcall=no
-;acceptdtmf=#
-;
-; Define endcall to allow an agent to hangup a call with a
-; DTMF keypress. Default is "yes". Use the enddtmf option to
-; configure which DTMF key will end a call. The default is
-; '*'.
-;
-;endcall=yes
-;enddtmf=*
-;
-; Define wrapuptime.  This is the minimum amount of time when
-; after disconnecting before the caller can receive a new call
-; note this is in milliseconds.
-;
+; Set the minimum amount of time after disconnecting a call before
+; the agent can receive a new call in milliseconds.
+; The channel variable AGENTWRAPUPTIME overrides on agent login.
+; Default is 0.
 ;wrapuptime=5000
 ;
-; Define the default musiconhold for agents
-; musiconhold => music_class
+; Set the musiconhold class for the agent.
+; Default is "default".
+;musiconhold=default
 ;
-;musiconhold => default
-;
-; Define the default good bye sound file for agents
-; default to vm-goodbye
-;
-;goodbye => goodbye_file
-;
-; Define updatecdr. This is whether or not to change the source
-; channel in the CDR record for this call to agent/agent_id so
-; that we know which agent generates the call
-;
-;updatecdr=no
-;
-; Group memberships for agents (may change in mid-file)
-;
-;group=3
-;group=1,2
-;group=
-;
-; --------------------------------------------------
-; This section is devoted to recording agent's calls
-; The keywords are global to the chan_agent channel driver
-;
-; Enable recording calls addressed to agents. It's turned off by default.
+; Enable recording calls the agent takes automatically by invoking the
+; DTMF automixmon feature when the agent connects to a caller.
+; See features.conf.sample for information about the automixmon feature.
+; Default is "no".
 ;recordagentcalls=yes
 ;
-; The format to be used to record the calls: wav, gsm, wav49.
-; By default its "wav".
-;recordformat=gsm
+; The sound file played to alert the agent when a call is present.
+; Default is "beep".
+;custom_beep=beep
 ;
-; The text to be added to the name of the recording. Allows forming a url link.
-;urlprefix=http://localhost/calls/
-;
-; The optional directory to save the conversations in. The default is
-; /var/spool/asterisk/monitor
-;savecallsin=/var/calls
-;
-; An optional custom beep sound file to play to always-connected agents.
-;custom_beep=beep
+; A friendly name for the agent used in log messages.
+; Default is "".
+;fullname=Mark Spencer
 ;
 ; --------------------------------------------------
 ;
-; This section contains the agent definitions, in the form:
+; This section contains example agent definitions:
 ;
-; agent => agentid,agentpassword,name
+; Define a template called my-agents:
+;[my-agents](!)
+;autologoff=15
+;ackcall=yes
+;acceptdtmf=##
 ;
-;agent => 1001,4321,Mark Spencer
-;agent => 1002,4321,Will Meadows
+; Define agent 1001 using the my-agents template:
+;[1001](my-agents)
+;fullname=Mark Spencer
+;
+; Define agent 1002 using the my-agents template:
+;[1002](my-agents)
+;fullname=Will Meadows

Modified: team/mmichelson/queue_bugbug/configs/queues.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/configs/queues.conf.sample?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/configs/queues.conf.sample (original)
+++ team/mmichelson/queue_bugbug/configs/queues.conf.sample Tue Jul 16 12:01:15 2013
@@ -543,18 +543,7 @@
 ;member => DAHDI/1
 ;member => DAHDI/2,10
 ;member => DAHDI/3,10,Bob Johnson
-;member => Agent/1001
-;member => Agent/1002
+;member => Local/1001 at agents,0,May Flowers,Agent:1001
+;member => Local/1002 at agents,0,John Doe,Agent:1002
 ;member => Local/1000 at default,0,John Smith,SIP/1000
 ;member => Local/2000 at default,0,Lorem Ipsum,SIP/2000,no
-
-;
-; Note that using agent groups is probably not what you want.  Strategies do
-; not propagate down to the Agent system so if you want round robin, least
-; recent, etc, you should list all the agents in this file individually and not
-; use agent groups.
-;
-;member => Agent/@1		; Any agent in group 1
-;member => Agent/:1,1		; Any agent in group 1, wait for first
-                                ; available, but consider with penalty
-

Modified: team/mmichelson/queue_bugbug/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/include/asterisk/bridging.h?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/include/asterisk/bridging.h (original)
+++ team/mmichelson/queue_bugbug/include/asterisk/bridging.h Tue Jul 16 12:01:15 2013
@@ -1651,7 +1651,7 @@
 
 /*! Reason the the after bridge callback will not be called. */
 enum ast_after_bridge_cb_reason {
-	/*! The datastore is being destroyed.  Likely due to hangup. */
+	/*! The datastore is being destroyed.  Likely due to hangup. (Enum value must be zero.) */
 	AST_AFTER_BRIDGE_CB_REASON_DESTROY,
 	/*! Something else replaced the callback with another. */
 	AST_AFTER_BRIDGE_CB_REASON_REPLACED,
@@ -1670,6 +1670,9 @@
  * \param reason Reason callback is failing.
  * \param data Extra data what setup the callback wanted to pass.
  *
+ * \note Called when the channel leaves the bridging system or
+ * is destroyed.
+ *
  * \return Nothing
  */
 typedef void (*ast_after_bridge_cb_failed)(enum ast_after_bridge_cb_reason reason, void *data);
@@ -1709,6 +1712,9 @@
  *
  * \note chan is locked by this function.
  *
+ * \note failed is called when the channel leaves the bridging
+ * system or is destroyed.
+ *
  * \retval 0 on success.
  * \retval -1 on error.
  */

Modified: team/mmichelson/queue_bugbug/include/asterisk/config_options.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/include/asterisk/config_options.h?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/include/asterisk/config_options.h (original)
+++ team/mmichelson/queue_bugbug/include/asterisk/config_options.h Tue Jul 16 12:01:15 2013
@@ -461,7 +461,7 @@
 /*! \brief Process a config info via the options registered with an aco_info
  *
  * \param info The config_options_info to be used for handling the config
- * \param reload Whether or not this is a reload
+ * \param reload Non-zero if this is for a reload.
  *
  * \retval ACO_PROCESS_OK Success
  * \retval ACO_PROCESS_ERROR Failure

Modified: team/mmichelson/queue_bugbug/include/asterisk/stasis_channels.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/include/asterisk/stasis_channels.h?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/include/asterisk/stasis_channels.h (original)
+++ team/mmichelson/queue_bugbug/include/asterisk/stasis_channels.h Tue Jul 16 12:01:15 2013
@@ -145,7 +145,7 @@
  *
  * \param chan The channel from which to generate a snapshot
  *
- * \retval pointer on success (must be ast_freed)
+ * \retval pointer on success (must be unreffed)
  * \retval NULL on error
  */
 struct ast_channel_snapshot *ast_channel_snapshot_create(
@@ -434,6 +434,22 @@
  * \retval A stasis message type
  */
 struct stasis_message_type *ast_channel_monitor_stop_type(void);
+
+/*!
+ * \since 12.0.0
+ * \brief Message type for agent login on a channel
+ *
+ * \retval A stasis message type
+ */
+struct stasis_message_type *ast_channel_agent_login_type(void);
+
+/*!
+ * \since 12.0.0
+ * \brief Message type for agent logoff on a channel
+ *
+ * \retval A stasis message type
+ */
+struct stasis_message_type *ast_channel_agent_logoff_type(void);
 
 /*!
  * \since 12

Modified: team/mmichelson/queue_bugbug/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/main/bridging.c?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/main/bridging.c (original)
+++ team/mmichelson/queue_bugbug/main/bridging.c Tue Jul 16 12:01:15 2013
@@ -3242,14 +3242,69 @@
 	return bridge_channel;
 }
 
-struct after_bridge_cb_ds {
+struct after_bridge_cb_node {
+	/*! Next list node. */
+	AST_LIST_ENTRY(after_bridge_cb_node) list;
 	/*! Desired callback function. */
 	ast_after_bridge_cb callback;
 	/*! After bridge callback will not be called and destroy any resources data may contain. */
 	ast_after_bridge_cb_failed failed;
 	/*! Extra data to pass to the callback. */
 	void *data;
+	/*! Reason the after bridge callback failed. */
+	enum ast_after_bridge_cb_reason reason;
 };
+
+struct after_bridge_cb_ds {
+	/*! After bridge callbacks container. */
+	AST_LIST_HEAD(, after_bridge_cb_node) callbacks;
+};
+
+/*!
+ * \internal
+ * \brief Indicate after bridge callback failed.
+ * \since 12.0.0
+ *
+ * \param node After bridge callback node.
+ *
+ * \return Nothing
+ */
+static void after_bridge_cb_failed(struct after_bridge_cb_node *node)
+{
+	if (node->failed) {
+		node->failed(node->reason, node->data);
+		node->failed = NULL;
+	}
+}
+
+/*!
+ * \internal
+ * \brief Run discarding any after bridge callbacks.
+ * \since 12.0.0
+ *
+ * \param after_bridge After bridge callback container process.
+ * \param reason Why are we doing this.
+ *
+ * \return Nothing
+ */
+static void after_bridge_cb_run_discard(struct after_bridge_cb_ds *after_bridge, enum ast_after_bridge_cb_reason reason)
+{
+	struct after_bridge_cb_node *node;
+
+	for (;;) {
+		AST_LIST_LOCK(&after_bridge->callbacks);
+		node = AST_LIST_REMOVE_HEAD(&after_bridge->callbacks, list);
+		AST_LIST_UNLOCK(&after_bridge->callbacks);
+		if (!node) {
+			break;
+		}
+		if (!node->reason) {
+			node->reason = reason;
+		}
+		after_bridge_cb_failed(node);
+		ast_free(node);
+	}
+}
 
 /*!
  * \internal
@@ -3264,10 +3319,9 @@
 {
 	struct after_bridge_cb_ds *after_bridge = data;
 
-	if (after_bridge->failed) {
-		after_bridge->failed(AST_AFTER_BRIDGE_CB_REASON_DESTROY, after_bridge->data);
-		after_bridge->failed = NULL;
-	}
+	after_bridge_cb_run_discard(after_bridge, AST_AFTER_BRIDGE_CB_REASON_DESTROY);
+
+	AST_LIST_HEAD_DESTROY(&after_bridge->callbacks);
 	ast_free(after_bridge);
 }
 
@@ -3284,7 +3338,6 @@
  */
 static void after_bridge_cb_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 {
-	/* There can be only one.  Discard any already on the new channel. */
 	ast_after_bridge_callback_discard(new_chan, AST_AFTER_BRIDGE_CB_REASON_MASQUERADE);
 }
 
@@ -3296,82 +3349,144 @@
 
 /*!
  * \internal
- * \brief Remove channel after the bridge callback and return it.
+ * \brief Setup/create an after bridge callback datastore container.
  * \since 12.0.0
  *
- * \param chan Channel to remove after bridge callback.
- *
- * \retval datastore on success.
- * \retval NULL on error or not found.
- */
-static struct ast_datastore *after_bridge_cb_remove(struct ast_channel *chan)
-{
-	struct ast_datastore *datastore;
-
-	ast_channel_lock(chan);
-	datastore = ast_channel_datastore_find(chan, &after_bridge_cb_info, NULL);
-	if (datastore && ast_channel_datastore_remove(chan, datastore)) {
-		datastore = NULL;
-	}
-	ast_channel_unlock(chan);
-
-	return datastore;
-}
-
-void ast_after_bridge_callback_discard(struct ast_channel *chan, enum ast_after_bridge_cb_reason reason)
-{
-	struct ast_datastore *datastore;
-
-	datastore = after_bridge_cb_remove(chan);
-	if (datastore) {
-		struct after_bridge_cb_ds *after_bridge = datastore->data;
-
-		if (after_bridge && after_bridge->failed) {
-			after_bridge->failed(reason, after_bridge->data);
-			after_bridge->failed = NULL;
-		}
-		ast_datastore_free(datastore);
-	}
-}
-
-/*!
- * \internal
- * \brief Run any after bridge callback if possible.
- * \since 12.0.0
- *
- * \param chan Channel to run after bridge callback.
- *
- * \return Nothing
- */
-static void after_bridge_callback_run(struct ast_channel *chan)
+ * \param chan Channel to setup/create the after bridge callback container on.
+ *
+ * \retval after_bridge datastore container on success.
+ * \retval NULL on error.
+ */
+static struct after_bridge_cb_ds *after_bridge_cb_setup(struct ast_channel *chan)
 {
 	struct ast_datastore *datastore;
 	struct after_bridge_cb_ds *after_bridge;
-
-	if (ast_check_hangup(chan)) {
+	SCOPED_CHANNELLOCK(lock, chan);
+
+	datastore = ast_channel_datastore_find(chan, &after_bridge_cb_info, NULL);
+	if (datastore) {
+		return datastore->data;
+	}
+
+	/* Create a new datastore. */
+	datastore = ast_datastore_alloc(&after_bridge_cb_info, NULL);
+	if (!datastore) {
+		return NULL;
+	}
+	after_bridge = ast_calloc(1, sizeof(*after_bridge));
+	if (!after_bridge) {
+		ast_datastore_free(datastore);
+		return NULL;
+	}
+	AST_LIST_HEAD_INIT(&after_bridge->callbacks);
+	datastore->data = after_bridge;
+	ast_channel_datastore_add(chan, datastore);
+
+	return datastore->data;
+}
+
+/*!
+ * \internal
+ * \brief Find an after bridge callback datastore container.
+ * \since 12.0.0
+ *
+ * \param chan Channel to find the after bridge callback container on.
+ *
+ * \retval after_bridge datastore container on success.
+ * \retval NULL on error.
+ */
+static struct after_bridge_cb_ds *after_bridge_cb_find(struct ast_channel *chan)
+{
+	struct ast_datastore *datastore;
+	SCOPED_CHANNELLOCK(lock, chan);
+
+	datastore = ast_channel_datastore_find(chan, &after_bridge_cb_info, NULL);
+	if (!datastore) {
+		return NULL;
+	}
+	return datastore->data;
+}
+
+/*!
+ * \internal
+ * \brief Run any after bridge callback.
+ * \since 12.0.0
+ *
+ * \param chan Channel to run after bridge callback.
+ *
+ * \return Nothing
+ */
+static void after_bridge_callback_run(struct ast_channel *chan)
+{
+	struct after_bridge_cb_ds *after_bridge;
+	struct after_bridge_cb_node *node;
+
+	after_bridge = after_bridge_cb_find(chan);
+	if (!after_bridge) {
 		return;
 	}
 
-	/* Get after bridge goto datastore. */
-	datastore = after_bridge_cb_remove(chan);
-	if (!datastore) {
+	for (;;) {
+		AST_LIST_LOCK(&after_bridge->callbacks);
+		node = AST_LIST_REMOVE_HEAD(&after_bridge->callbacks, list);
+		AST_LIST_UNLOCK(&after_bridge->callbacks);
+		if (!node) {
+			break;
+		}
+		if (node->reason) {
+			after_bridge_cb_failed(node);
+		} else {
+			node->failed = NULL;
+			node->callback(chan, node->data);
+		}
+		ast_free(node);
+	}
+}
+
+/*!
+ * \internal
+ * \brief Run discarding any after bridge callbacks.
+ * \since 12.0.0
+ *
+ * \param chan Channel to run after bridge callback.
+ *
+ * \return Nothing
+ */
+static void after_bridge_callback_run_discard(struct ast_channel *chan, enum ast_after_bridge_cb_reason reason)
+{
+	struct after_bridge_cb_ds *after_bridge;
+
+	after_bridge = after_bridge_cb_find(chan);
+	if (!after_bridge) {
 		return;
 	}
 
-	after_bridge = datastore->data;
-	if (after_bridge) {
-		after_bridge->failed = NULL;
-		after_bridge->callback(chan, after_bridge->data);
-	}
-
-	/* Discard after bridge callback datastore. */
-	ast_datastore_free(datastore);
+	after_bridge_cb_run_discard(after_bridge, reason);
+}
+
+void ast_after_bridge_callback_discard(struct ast_channel *chan, enum ast_after_bridge_cb_reason reason)
+{
+	struct after_bridge_cb_ds *after_bridge;
+	struct after_bridge_cb_node *node;
+
+	after_bridge = after_bridge_cb_find(chan);
+	if (!after_bridge) {
+		return;
+	}
+
+	AST_LIST_LOCK(&after_bridge->callbacks);
+	node = AST_LIST_LAST(&after_bridge->callbacks);
+	if (node && !node->reason) {
+		node->reason = reason;
+	}
+	AST_LIST_UNLOCK(&after_bridge->callbacks);
 }
 
 int ast_after_bridge_callback_set(struct ast_channel *chan, ast_after_bridge_cb callback, ast_after_bridge_cb_failed failed, void *data)
 {
-	struct ast_datastore *datastore;
 	struct after_bridge_cb_ds *after_bridge;
+	struct after_bridge_cb_node *new_node;
+	struct after_bridge_cb_node *last_node;
 
 	/* Sanity checks. */
 	ast_assert(chan != NULL);
@@ -3379,29 +3494,28 @@
 		return -1;
 	}
 
-	/* Create a new datastore. */
-	datastore = ast_datastore_alloc(&after_bridge_cb_info, NULL);
-	if (!datastore) {
+	after_bridge = after_bridge_cb_setup(chan);
+	if (!after_bridge) {
 		return -1;
 	}
-	after_bridge = ast_calloc(1, sizeof(*after_bridge));
-	if (!after_bridge) {
-		ast_datastore_free(datastore);
+
+	/* Create a new callback node. */
+	new_node = ast_calloc(1, sizeof(*new_node));
+	if (!new_node) {
 		return -1;
 	}
-
-	/* Initialize it. */
-	after_bridge->callback = callback;
-	after_bridge->failed = failed;
-	after_bridge->data = data;
-	datastore->data = after_bridge;
-
-	/* Put it on the channel replacing any existing one. */
-	ast_channel_lock(chan);
-	ast_after_bridge_callback_discard(chan, AST_AFTER_BRIDGE_CB_REASON_REPLACED);
-	ast_channel_datastore_add(chan, datastore);
-	ast_channel_unlock(chan);
-
+	new_node->callback = callback;
+	new_node->failed = failed;
+	new_node->data = data;
+
+	/* Put it in the container disabling any previously active one. */
+	AST_LIST_LOCK(&after_bridge->callbacks);
+	last_node = AST_LIST_LAST(&after_bridge->callbacks);
+	if (last_node && !last_node->reason) {
+		last_node->reason = AST_AFTER_BRIDGE_CB_REASON_REPLACED;
+	}
+	AST_LIST_INSERT_TAIL(&after_bridge->callbacks, new_node, list);
+	AST_LIST_UNLOCK(&after_bridge->callbacks);
 	return 0;
 }
 
@@ -3866,7 +3980,7 @@
 	ast_bridge_features_destroy(bridge_channel->features);
 	bridge_channel->features = NULL;
 
-	ast_after_bridge_callback_discard(bridge_channel->chan, AST_AFTER_BRIDGE_CB_REASON_DEPART);
+	after_bridge_callback_run_discard(bridge_channel->chan, AST_AFTER_BRIDGE_CB_REASON_DEPART);
 	ast_after_bridge_goto_discard(bridge_channel->chan);
 
 	return NULL;

Modified: team/mmichelson/queue_bugbug/main/stasis_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/main/stasis_channels.c?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/main/stasis_channels.c (original)
+++ team/mmichelson/queue_bugbug/main/stasis_channels.c Tue Jul 16 12:01:15 2013
@@ -53,6 +53,35 @@
 					<para>The new value of the variable.</para>
 				</parameter>
 			</syntax>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="AgentLogin">
+		<managerEventInstance class="EVENT_FLAG_AGENT">
+			<synopsis>Raised when an Agent has logged in.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Agent">
+					<para>Agent ID of the agent.</para>
+				</parameter>
+			</syntax>
+			<see-also>
+				<ref type="application">AgentLogin</ref>
+				<ref type="managerEvent">AgentLogoff</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="AgentLogoff">
+		<managerEventInstance class="EVENT_FLAG_AGENT">
+			<synopsis>Raised when an Agent has logged off.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentLogin']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Logintime">
+					<para>The number of seconds the agent was logged in.</para>
+				</parameter>
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">AgentLogin</ref>
+			</see-also>
 		</managerEventInstance>
 	</managerEvent>
 ***/
@@ -625,6 +654,44 @@
 		"Variable: %s\r\n"
 		"Value: %s\r\n",
 		ast_str_buffer(channel_event_string), variable, value);
+}
+
+static struct ast_manager_event_blob *agent_login_to_ami(struct stasis_message *msg)
+{
+	RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
+	RAII_VAR(struct ast_str *, party_string, ast_str_create(256), ast_free);
+	struct ast_channel_blob *obj = stasis_message_data(msg);
+	const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
+
+	channel_string = ast_manager_build_channel_state_string(obj->snapshot);
+	if (!channel_string) {
+		return NULL;
+	}
+
+	return ast_manager_event_blob_create(EVENT_FLAG_AGENT, "AgentLogin",
+		"%s"
+		"Agent: %s\r\n",
+		ast_str_buffer(channel_string), agent);
+}
+
+static struct ast_manager_event_blob *agent_logoff_to_ami(struct stasis_message *msg)
+{
+	RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
+	RAII_VAR(struct ast_str *, party_string, ast_str_create(256), ast_free);
+	struct ast_channel_blob *obj = stasis_message_data(msg);
+	const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
+	long logintime = ast_json_integer_get(ast_json_object_get(obj->blob, "logintime"));
+
+	channel_string = ast_manager_build_channel_state_string(obj->snapshot);
+	if (!channel_string) {
+		return NULL;
+	}
+
+	return ast_manager_event_blob_create(EVENT_FLAG_AGENT, "AgentLogoff",
+		"%s"
+		"Agent: %s\r\n"
+		"Logintime: %ld\r\n",
+		ast_str_buffer(channel_string), agent, logintime);
 }
 
 void ast_publish_channel_state(struct ast_channel *chan)
@@ -827,6 +894,12 @@
 STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_stop_type);
 STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_start_type);
 STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_stop_type);
+STASIS_MESSAGE_TYPE_DEFN(ast_channel_agent_login_type,
+	.to_ami = agent_login_to_ami,
+	);
+STASIS_MESSAGE_TYPE_DEFN(ast_channel_agent_logoff_type,
+	.to_ami = agent_logoff_to_ami,
+	);
 
 /*! @} */
 
@@ -853,6 +926,8 @@
 	STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_moh_stop_type);
 	STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_monitor_start_type);
 	STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_monitor_stop_type);
+	STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_agent_login_type);
+	STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_agent_logoff_type);
 }
 
 void ast_stasis_channels_init(void)
@@ -876,6 +951,8 @@
 	STASIS_MESSAGE_TYPE_INIT(ast_channel_moh_stop_type);
 	STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_start_type);
 	STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_stop_type);
+	STASIS_MESSAGE_TYPE_INIT(ast_channel_agent_login_type);
+	STASIS_MESSAGE_TYPE_INIT(ast_channel_agent_logoff_type);
 
 	channel_topic_all = stasis_topic_create("ast_channel_topic_all");
 	channel_topic_all_cached = stasis_caching_topic_create(channel_topic_all, channel_snapshot_get_id);

Modified: team/mmichelson/queue_bugbug/res/res_http_websocket.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/res/res_http_websocket.c?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/res/res_http_websocket.c (original)
+++ team/mmichelson/queue_bugbug/res/res_http_websocket.c Tue Jul 16 12:01:15 2013
@@ -653,7 +653,7 @@
 		return 0;
 	}
 
-	ast_verb(2, "WebSocket connection from '%s' for protocol '%s' accepted using version '%d'\n", ast_sockaddr_stringify(&ser->remote_address), protocol, version);
+	ast_verb(2, "WebSocket connection from '%s' for protocol '%s' accepted using version '%d'\n", ast_sockaddr_stringify(&ser->remote_address), protocol ? : "", version);
 
 	/* Populate the session with all the needed details */
 	session->f = ser->f;

Modified: team/mmichelson/queue_bugbug/res/res_stasis_http.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/res/res_stasis_http.c?view=diff&rev=394458&r1=394457&r2=394458
==============================================================================
--- team/mmichelson/queue_bugbug/res/res_stasis_http.c (original)
+++ team/mmichelson/queue_bugbug/res/res_stasis_http.c Tue Jul 16 12:01:15 2013
@@ -90,6 +90,9 @@
 				</configOption>
 				<configOption name="auth_realm">
 					<synopsis>Realm to use for authentication. Defaults to Asterisk REST Interface.</synopsis>
+				</configOption>
+				<configOption name="allowed_origins">
+					<synopsis>Comma separated list of allowed origins, for Cross-Origin Resource Sharing. May be set to * to allow all origins.</synopsis>
 				</configOption>
 			</configObject>
 




More information about the asterisk-commits mailing list