[asterisk-commits] qwell: trunk r390901 - in /trunk: ./ apps/ configs/ main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Jun 7 14:51:28 CDT 2013
Author: qwell
Date: Fri Jun 7 14:51:19 2013
New Revision: 390901
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=390901
Log:
Make app_queue AMI events more consistent. Give Join/Leave more useful names.
This also removes the eventwhencalled and eventmemberstatus configuration
options. These events can just be filtered via manager.conf blacklists.
(closes issue ASTERISK-21469)
Review: https://reviewboard.asterisk.org/r/2586/
Modified:
trunk/CHANGES
trunk/apps/app_queue.c
trunk/configs/queues.conf.sample
trunk/main/manager.c
Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=390901&r1=390900&r2=390901
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Fri Jun 7 14:51:19 2013
@@ -106,6 +106,11 @@
core, and is now two events: Hold and Unhold. The status field has been
removed.
+ * The AMI events in app_queue have been made more consistent with each other.
+ Events that reference channels (QueueCaller* and Agent*) will show
+ information about each channel. The (infamous) "Join" and "Leave" AMI
+ events have been changed to "QueueCallerJoin" and "QueueCallerLeave".
+
AGI (Asterisk Gateway Interface)
------------------
* The manager event AGIExec has been split into AGIExecStart and AGIExecEnd.
@@ -242,6 +247,11 @@
Note: the suffix '_avail' after the queuename.
Reports 'InUse' for no logged in agents or no free agents.
Reports 'Idle' when an agent is free.
+
+ * The configuration options eventwhencalled and eventmemberstatus have been
+ removed. As a result, the AMI events QueueMemberStatus, AgentCalled,
+ AgentConnect, AgentComplete, AgentDump, and AgentRingNoAnswer will always be
+ sent. The "Variable" fields will also no longer exist on the Agent* events.
Core
------------------
Modified: trunk/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_queue.c?view=diff&rev=390901&r1=390900&r2=390901
==============================================================================
--- trunk/apps/app_queue.c (original)
+++ trunk/apps/app_queue.c Fri Jun 7 14:51:19 2013
@@ -108,6 +108,7 @@
#include "asterisk/term.h"
#include "asterisk/dial.h"
#include "asterisk/stasis_channels.h"
+#include "asterisk/stasis_message_router.h"
#include "asterisk/bridging.h"
/* Define, to debug reference counts on queues, without debugging reference counts on queue members */
@@ -827,7 +828,6 @@
<description>
</description>
</manager>
-
<manager name="QueueMemberRingInUse" language="en_US">
<synopsis>
Set the ringinuse value for a queue member.
@@ -841,7 +841,6 @@
<description>
</description>
</manager>
-
<manager name="QueueRule" language="en_US">
<synopsis>
Queue Rules.
@@ -893,6 +892,275 @@
<description>
</description>
</manager>
+
+ <managerEvent language="en_US" name="QueueMemberStatus">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a Queue member's status has changed.</synopsis>
+ <syntax>
+ <parameter name="Queue">
+ <para>The name of the queue.</para>
+ </parameter>
+ <parameter name="MemberName">
+ <para>The name of the queue member.</para>
+ </parameter>
+ <parameter name="Interface">
+ <para>The queue member's channel technology or location.</para>
+ </parameter>
+ <parameter name="StateInterface">
+ <para>Channel technology or location from which to read device state changes.</para>
+ </parameter>
+ <parameter name="Membership">
+ <enumlist>
+ <enum name="dynamic"/>
+ <enum name="realtime"/>
+ <enum name="static"/>
+ </enumlist>
+ </parameter>
+ <parameter name="Penalty">
+ <para>The penalty associated with the queue member.</para>
+ </parameter>
+ <parameter name="CallsTaken">
+ <para>The number of calls this queue member has serviced.</para>
+ </parameter>
+ <parameter name="LastCall">
+ <para>The time this member last took a call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
+ </parameter>
+ <parameter name="Status">
+ <para>The numeric device state status of the queue member.</para>
+ <enumlist>
+ <enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>
+ <enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>
+ <enum name="2"><para>AST_DEVICE_INUSE</para></enum>
+ <enum name="3"><para>AST_DEVICE_BUSY</para></enum>
+ <enum name="4"><para>AST_DEVICE_INVALID</para></enum>
+ <enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>
+ <enum name="6"><para>AST_DEVICE_RINGING</para></enum>
+ <enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>
+ <enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>
+ </enumlist>
+ </parameter>
+ <parameter name="Paused">
+ <enumlist>
+ <enum name="0"/>
+ <enum name="1"/>
+ </enumlist>
+ </parameter>
+ <parameter name="Ringinuse">
+ <enumlist>
+ <enum name="0"/>
+ <enum name="1"/>
+ </enumlist>
+ </parameter>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="QueueMemberAdded">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a member is added to the queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
+ </syntax>
+ <see-also>
+ <ref type="managerEvent">QueueMemberRemoved</ref>
+ <ref type="application">AddQueueMember</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="QueueMemberRemoved">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a member is removed from the queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
+ </syntax>
+ <see-also>
+ <ref type="managerEvent">QueueMemberAdded</ref>
+ <ref type="application">RemoveQueueMember</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="QueueMemberPaused">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a member is paused/unpaused in the queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
+ <parameter name="Reason">
+ <para>The reason a member was paused.</para>
+ </parameter>
+ </syntax>
+ <see-also>
+ <ref type="application">PauseQueueMember</ref>
+ <ref type="application">UnPauseQueueMember</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="QueueMemberPenalty">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a member's penalty is changed.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
+ </syntax>
+ <see-also>
+ <ref type="function">QUEUE_MEMBER</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="QueueMemberRinginuse">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a member's ringinuse setting is changed.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
+ </syntax>
+ <see-also>
+ <ref type="function">QUEUE_MEMBER</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="QueueCallerJoin">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a caller joins a Queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
+ <parameter name="Position">
+ <para>This channel's current position in the queue.</para>
+ </parameter>
+ <parameter name="Count">
+ <para>The total number of channels in the queue.</para>
+ </parameter>
+ </syntax>
+ <see-also>
+ <ref type="managerEvent">QueueCallerLeave</ref>
+ <ref type="application">Queue</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="QueueCallerLeave">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a caller leaves a Queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Count'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
+ </syntax>
+ <see-also>
+ <ref type="managerEvent">QueueCallerJoin</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="QueueCallerAbandon">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a caller abandons the queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
+ <parameter name="OriginalPosition">
+ <para>The channel's original position in the queue.</para>
+ </parameter>
+ <parameter name="HoldTime">
+ <para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
+ </parameter>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="AgentCalled">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when an queue member is notified of a caller in the queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
+ </syntax>
+ <see-also>
+ <ref type="managerEvent">AgentRingNoAnswer</ref>
+ <ref type="managerEvent">AgentComplete</ref>
+ <ref type="managerEvent">AgentConnect</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="AgentRingNoAnswer">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a queue member is notified of a caller in the queue and fails to answer.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
+ <parameter name="RingTime">
+ <para>The time the queue member was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
+ </parameter>
+ </syntax>
+ <see-also>
+ <ref type="managerEvent">AgentCalled</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="AgentComplete">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a queue member has finished servicing a caller in the queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
+ <parameter name="TalkTime">
+ <para>The time the queue member talked with the caller in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
+ </parameter>
+ <parameter name="Reason">
+ <enumlist>
+ <enum name="caller"/>
+ <enum name="agent"/>
+ <enum name="transfer"/>
+ </enumlist>
+ </parameter>
+ </syntax>
+ <see-also>
+ <ref type="managerEvent">AgentCalled</ref>
+ <ref type="managerEvent">AgentConnect</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="AgentDump">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a queue member hangs up on a caller in the queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
+ </syntax>
+ <see-also>
+ <ref type="managerEvent">AgentCalled</ref>
+ <ref type="managerEvent">AgentConnect</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="AgentConnect">
+ <managerEventInstance class="EVENT_FLAG_AGENT">
+ <synopsis>Raised when a queue member answers and is bridged to a caller in the queue.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='DialBegin']/managerEventInstance/syntax/parameter[contains(@name, 'Dest')])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='RingTime'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
+ </syntax>
+ <see-also>
+ <ref type="managerEvent">AgentCalled</ref>
+ <ref type="managerEvent">AgentComplete</ref>
+ <ref type="managerEvent">AgentDump</ref>
+ </see-also>
+ </managerEventInstance>
+ </managerEvent>
***/
enum {
@@ -1248,7 +1516,6 @@
/*! Sound files: Custom announce, no default */
struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
unsigned int dead:1;
- unsigned int eventwhencalled:2;
unsigned int ringinuse:1;
unsigned int setinterfacevar:1;
unsigned int setqueuevar:1;
@@ -1259,7 +1526,6 @@
unsigned int announceholdtime:2;
unsigned int announceposition:3;
int strategy:4;
- unsigned int maskmemberstatus:1;
unsigned int realtime:1;
unsigned int found:1;
unsigned int relativeperiodicannounce:1;
@@ -1512,7 +1778,7 @@
q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
ao2_unlock(q);
-
+
pbx_builtin_setvar_multiple(chan, interfacevar);
} else {
ao2_unlock(q);
@@ -1542,6 +1808,184 @@
new->parent = q;
new->pos = ++(*pos);
new->opos = *pos;
+}
+
+struct stasis_message_type *queue_caller_join_type(void);
+struct stasis_message_type *queue_caller_leave_type(void);
+struct stasis_message_type *queue_caller_abandon_type(void);
+
+struct stasis_message_type *queue_member_status_type(void);
+struct stasis_message_type *queue_member_added_type(void);
+struct stasis_message_type *queue_member_removed_type(void);
+struct stasis_message_type *queue_member_pause_type(void);
+struct stasis_message_type *queue_member_penalty_type(void);
+struct stasis_message_type *queue_member_ringinuse_type(void);
+
+struct stasis_message_type *queue_agent_called_type(void);
+struct stasis_message_type *queue_agent_connect_type(void);
+struct stasis_message_type *queue_agent_complete_type(void);
+struct stasis_message_type *queue_agent_dump_type(void);
+struct stasis_message_type *queue_agent_ringnoanswer_type(void);
+
+STASIS_MESSAGE_TYPE_DEFN(queue_caller_join_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_caller_leave_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_caller_abandon_type);
+
+STASIS_MESSAGE_TYPE_DEFN(queue_member_status_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_member_added_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_member_removed_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_member_pause_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_member_penalty_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_member_ringinuse_type);
+
+STASIS_MESSAGE_TYPE_DEFN(queue_agent_called_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_agent_connect_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_agent_complete_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_agent_dump_type);
+STASIS_MESSAGE_TYPE_DEFN(queue_agent_ringnoanswer_type);
+
+static void queue_channel_manager_event(void *data,
+ struct stasis_subscription *sub, struct stasis_topic *topic,
+ struct stasis_message *message)
+{
+ const char *type = data;
+ struct ast_channel_blob *obj = stasis_message_data(message);
+ RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
+ RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
+
+ channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
+ if (!channel_event_string) {
+ return;
+ }
+
+ event_string = ast_manager_str_from_json_object(obj->blob, NULL);
+ if (!event_string) {
+ return;
+ }
+
+ manager_event(EVENT_FLAG_AGENT, type,
+ "%s"
+ "%s",
+ ast_str_buffer(channel_event_string),
+ ast_str_buffer(event_string));
+}
+
+static void queue_multi_channel_manager_event(void *data,
+ struct stasis_subscription *sub, struct stasis_topic *topic,
+ struct stasis_message *message)
+{
+ const char *type = data;
+ struct ast_multi_channel_blob *obj = stasis_message_data(message);
+ struct ast_channel_snapshot *caller;
+ struct ast_channel_snapshot *agent;
+ RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
+ RAII_VAR(struct ast_str *, agent_event_string, NULL, ast_free);
+ RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
+
+ caller = ast_multi_channel_blob_get_channel(obj, "caller");
+ agent = ast_multi_channel_blob_get_channel(obj, "agent");
+
+ caller_event_string = ast_manager_build_channel_state_string(caller);
+ agent_event_string = ast_manager_build_channel_state_string_prefix(agent, "Dest");
+
+ if (!caller_event_string || !agent_event_string) {
+ return;
+ }
+
+ event_string = ast_manager_str_from_json_object(ast_multi_channel_blob_get_json(obj), NULL);
+ if (!event_string) {
+ return;
+ }
+
+ manager_event(EVENT_FLAG_AGENT, type,
+ "%s"
+ "%s"
+ "%s",
+ ast_str_buffer(caller_event_string),
+ ast_str_buffer(agent_event_string),
+ ast_str_buffer(event_string));
+}
+
+static void queue_member_manager_event(void *data,
+ struct stasis_subscription *sub, struct stasis_topic *topic,
+ struct stasis_message *message)
+{
+ const char *type = data;
+ struct ast_json_payload *payload = stasis_message_data(message);
+ struct ast_json *event = payload->json;
+ RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
+
+ event_string = ast_manager_str_from_json_object(event, NULL);
+ if (!event_string) {
+ return;
+ }
+
+ manager_event(EVENT_FLAG_AGENT, type,
+ "%s", ast_str_buffer(event_string));
+}
+
+static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct ast_channel *agent, struct stasis_message_type *type, struct ast_json *blob)
+{
+ RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+ struct ast_channel_snapshot *caller_snapshot;
+ struct ast_channel_snapshot *agent_snapshot;
+
+ payload = ast_multi_channel_blob_create(blob);
+ if (!payload) {
+ return;
+ }
+
+ caller_snapshot = ast_channel_snapshot_create(caller);
+ agent_snapshot = ast_channel_snapshot_create(agent);
+
+ if (!caller_snapshot || !agent_snapshot) {
+ return;
+ }
+
+ ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
+ ast_multi_channel_blob_add_channel(payload, "agent", agent_snapshot);
+
+ msg = stasis_message_create(type, payload);
+ if (!msg) {
+ return;
+ }
+
+ stasis_publish(ast_channel_topic(caller), msg);
+}
+
+static void queue_publish_member_blob(struct stasis_message_type *type, struct ast_json *blob)
+{
+ RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+
+ payload = ast_json_payload_create(blob);
+ if (!payload) {
+ return;
+ }
+
+ msg = stasis_message_create(type, payload);
+ if (!msg) {
+ return;
+ }
+
+ stasis_publish(ast_manager_get_topic(), msg);
+}
+
+static struct ast_json *queue_member_blob_create(struct call_queue *q, struct member *mem)
+{
+ return ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: i}",
+ "Queue", q->name,
+ "MemberName", mem->membername,
+ "Interface", mem->interface,
+ "StateInterface", mem->state_interface,
+ "Membership", (mem->dynamic ? "dynamic" : (mem->realtime ? "realtime" : "static")),
+ "Penalty", mem->penalty,
+ "CallsTaken", mem->calls,
+ "LastCall", (int)mem->lastcall,
+ "Status", mem->status,
+ "Paused", mem->paused,
+ "Ringinuse", mem->ringinuse);
}
/*! \brief Check if members are available
@@ -1629,79 +2073,7 @@
{
m->status = status;
- if (q->maskmemberstatus) {
- return;
- }
-
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a Queue member's status has changed.</synopsis>
- <syntax>
- <parameter name="Queue">
- <para>The name of the queue.</para>
- </parameter>
- <parameter name="Location">
- <para>The queue member's channel technology or location.</para>
- </parameter>
- <parameter name="MemberName">
- <para>The name of the queue member.</para>
- </parameter>
- <parameter name="StateInterface">
- <para>Channel technology or location from which to read device state changes.</para>
- </parameter>
- <parameter name="Membership">
- <enumlist>
- <enum name="dynamic"/>
- <enum name="realtime"/>
- <enum name="static"/>
- </enumlist>
- </parameter>
- <parameter name="Penalty">
- <para>The penalty associated with the queue member.</para>
- </parameter>
- <parameter name="CallsTaken">
- <para>The number of calls this queue member has serviced.</para>
- </parameter>
- <parameter name="LastCall">
- <para>The time this member last took call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
- </parameter>
- <parameter name="Status">
- <para>The numeric device state status of the queue member.</para>
- <enumlist>
- <enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>
- <enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>
- <enum name="2"><para>AST_DEVICE_INUSE</para></enum>
- <enum name="3"><para>AST_DEVICE_BUSY</para></enum>
- <enum name="4"><para>AST_DEVICE_INVALID</para></enum>
- <enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>
- <enum name="6"><para>AST_DEVICE_RINGING</para></enum>
- <enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>
- <enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>
- </enumlist>
- </parameter>
- <parameter name="Paused">
- <enumlist>
- <enum name="0"/>
- <enum name="1"/>
- </enumlist>
- </parameter>
- </syntax>
- </managerEventInstance>
- ***/
- manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
- "Queue: %s\r\n"
- "Location: %s\r\n"
- "MemberName: %s\r\n"
- "StateInterface: %s\r\n"
- "Membership: %s\r\n"
- "Penalty: %d\r\n"
- "CallsTaken: %d\r\n"
- "LastCall: %d\r\n"
- "Status: %d\r\n"
- "Paused: %d\r\n",
- q->name, m->interface, m->membername, m->state_interface, m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
- m->penalty, m->calls, (int)m->lastcall, m->status, m->paused
- );
+ queue_publish_member_blob(queue_member_status_type(), queue_member_blob_create(q, m));
}
/*!
@@ -2010,8 +2382,6 @@
q->joinempty = 0;
q->leavewhenempty = 0;
q->memberdelay = 0;
- q->maskmemberstatus = 0;
- q->eventwhencalled = 0;
q->weight = 0;
q->timeoutrestart = 0;
q->periodicannouncefrequency = 0;
@@ -2399,14 +2769,6 @@
parse_empty_options(val, &q->joinempty, 1);
} else if (!strcasecmp(param, "leavewhenempty")) {
parse_empty_options(val, &q->leavewhenempty, 0);
- } else if (!strcasecmp(param, "eventmemberstatus")) {
- q->maskmemberstatus = !ast_true(val);
- } else if (!strcasecmp(param, "eventwhencalled")) {
- if (!strcasecmp(val, "vars")) {
- q->eventwhencalled = QUEUE_EVENT_VARIABLES;
- } else {
- q->eventwhencalled = ast_true(val) ? 1 : 0;
- }
} else if (!strcasecmp(param, "reportholdtime")) {
q->reportholdtime = ast_true(val);
} else if (!strcasecmp(param, "memberdelay")) {
@@ -2909,6 +3271,8 @@
if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen)) {
*reason = QUEUE_FULL;
} else if (*reason == QUEUE_UNKNOWN) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
/* There's space for us, put us at the right position inside
* the queue.
* Take into account the priority of the calling user */
@@ -2951,40 +3315,12 @@
}
res = 0;
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a channel joins a Queue.</synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
- <parameter name="Position">
- <para>This channel's current position in the queue.</para>
- </parameter>
- <parameter name="Count">
- <para>The total number of channels in the queue.</para>
- </parameter>
- </syntax>
- <see-also>
- <ref type="managerEvent">Leave</ref>
- <ref type="application">Queue</ref>
- </see-also>
- </managerEventInstance>
- ***/
- ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Join",
- "Channel: %s\r\n"
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "ConnectedLineNum: %s\r\n"
- "ConnectedLineName: %s\r\n"
- "Queue: %s\r\n"
- "Position: %d\r\n"
- "Count: %d\r\n"
- "Uniqueid: %s\r\n",
- ast_channel_name(qe->chan),
- S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
- S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
- S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
- S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
- q->name, qe->pos, q->count, ast_channel_uniqueid(qe->chan));
+
+ blob = ast_json_pack("{s: s, s: i, s: i}",
+ "Queue", q->name,
+ "Position", qe->pos,
+ "Count", q->count);
+ ast_channel_publish_blob(qe->chan, queue_caller_join_type(), blob);
ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
}
ao2_unlock(q);
@@ -3252,29 +3588,18 @@
prev = NULL;
for (current = q->head; current; current = current->next) {
if (current == qe) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
char posstr[20];
q->count--;
if (!q->count) {
ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s", q->name);
}
- /* Take us out of the queue */
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a channel leaves a Queue.</synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='Join']/managerEventInstance/syntax/parameter[@name='Count'])" />
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='Join']/managerEventInstance/syntax/parameter[@name='Position'])" />
- </syntax>
- <see-also>
- <ref type="managerEvent">Join</ref>
- </see-also>
- </managerEventInstance>
- ***/
- ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Leave",
- "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
- ast_channel_name(qe->chan), q->name, q->count, qe->pos, ast_channel_uniqueid(qe->chan));
+ blob = ast_json_pack("{s: s, s: i, s: i}",
+ "Queue", q->name,
+ "Position", qe->pos,
+ "Count", q->count);
+ ast_channel_publish_blob(qe->chan, queue_caller_leave_type(), blob);
ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
/* Take us out of the queue */
if (prev) {
@@ -3446,46 +3771,6 @@
o->stillgoing = 0;
ast_hangup(o->chan);
o->chan = NULL;
-}
-
-/*! \brief convert "\n" to "\nVariable: " ready for manager to use */
-static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
-{
- struct ast_str *buf = ast_str_thread_get(&ast_str_thread_global_buf, len + 1);
- const char *tmp;
-
- if (pbx_builtin_serialize_variables(chan, &buf)) {
- int i, j;
-
- /* convert "\n" to "\nVariable: " */
- strcpy(vars, "Variable: ");
- tmp = ast_str_buffer(buf);
-
- for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
- vars[j] = tmp[i];
-
- if (tmp[i + 1] == '\0') {
- break;
- }
- if (tmp[i] == '\n') {
- vars[j++] = '\r';
- vars[j++] = '\n';
-
- ast_copy_string(&(vars[j]), "Variable: ", len - j);
- j += 9;
- }
- }
- if (j > len - 3) {
- j = len - 3;
- }
- vars[j++] = '\r';
- vars[j++] = '\n';
- vars[j] = '\0';
- } else {
- /* there are no channel variables; leave it blank */
- *vars = '\0';
- }
- return vars;
}
/*!
@@ -3615,6 +3900,7 @@
char tech[256];
char *location;
const char *macrocontext, *macroexten;
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
/* on entry here, we know that tmp->chan == NULL */
if (!can_ring_entry(qe, tmp)) {
@@ -3728,54 +4014,11 @@
ast_channel_lock_both(tmp->chan, qe->chan);
- if (qe->parent->eventwhencalled) {
- char vars[2048];
-
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when an Agent is notified of a member in the queue.</synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
- <parameter name="AgentCalled">
- <para>The agent's technology or location.</para>
- </parameter>
- <parameter name="AgentName">
- <para>The name of the agent.</para>
- </parameter>
- <parameter name="Variable" required="no" multiple="yes">
- <para>Optional channel variables from the ChannelCalling channel</para>
- </parameter>
- </syntax>
- <see-also>
- <ref type="managerEvent">AgentRingNoAnswer</ref>
- <ref type="managerEvent">AgentComplete</ref>
- <ref type="managerEvent">AgentConnect</ref>
- </see-also>
- </managerEventInstance>
- ***/
- manager_event(EVENT_FLAG_AGENT, "AgentCalled",
- "Queue: %s\r\n"
- "AgentCalled: %s\r\n"
- "AgentName: %s\r\n"
- "ChannelCalling: %s\r\n"
- "DestinationChannel: %s\r\n"
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "ConnectedLineNum: %s\r\n"
- "ConnectedLineName: %s\r\n"
- "Context: %s\r\n"
- "Extension: %s\r\n"
- "Priority: %d\r\n"
- "Uniqueid: %s\r\n"
- "%s",
- qe->parent->name, tmp->interface, tmp->member->membername, ast_channel_name(qe->chan), ast_channel_name(tmp->chan),
- S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),
- S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
- S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),
- S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
- ast_channel_context(qe->chan), ast_channel_exten(qe->chan), ast_channel_priority(qe->chan), ast_channel_uniqueid(qe->chan),
- qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
- }
+ blob = ast_json_pack("{s: s, s: s, s: s}",
+ "Queue", qe->parent->name,
+ "Interface", tmp->interface,
+ "MemberName", tmp->member->membername);
+ queue_publish_multi_channel_blob(qe->chan, tmp->chan, queue_agent_called_type(), blob);
ast_channel_publish_dial(qe->chan, tmp->chan, tmp->interface, NULL);
@@ -3955,45 +4198,33 @@
if (!qe->parent->randomperiodicannounce) {
qe->last_periodic_announce_sound++;
}
-
+
return res;
}
/*! \brief Record that a caller gave up on waiting in queue */
static void record_abandoned(struct queue_ent *qe)
{
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
set_queue_variables(qe->parent, qe->chan);
ao2_lock(qe->parent);
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when an caller abandons the queue.</synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='Join']/managerEventInstance/syntax/parameter[@name='Position'])" />
- <parameter name="OriginalPosition">
- <para>The channel's original position in the queue.</para>
- </parameter>
- <parameter name="HoldTime">
- <para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
- </parameter>
- </syntax>
- </managerEventInstance>
- ***/
- manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
- "Queue: %s\r\n"
- "Uniqueid: %s\r\n"
- "Position: %d\r\n"
- "OriginalPosition: %d\r\n"
- "HoldTime: %d\r\n",
- qe->parent->name, ast_channel_uniqueid(qe->chan), qe->pos, qe->opos, (int)(time(NULL) - qe->start));
+ blob = ast_json_pack("{s: s, s: i, s: i}",
+ "Queue", qe->parent->name,
+ "Position", qe->pos,
+ "OriginalPosition", qe->opos,
+ "HoldTime", (int)(time(NULL) - qe->start));
+ ast_channel_publish_blob(qe->chan, queue_caller_abandon_type(), blob);
qe->parent->callsabandoned++;
ao2_unlock(qe->parent);
}
/*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
-static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int autopause)
-{
+static void rna(int rnatime, struct queue_ent *qe, struct ast_channel *peer, char *interface, char *membername, int autopause)
+{
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
/* Stop ringing, and resume MOH if specified */
@@ -4002,43 +4233,13 @@
ast_moh_start(qe->chan, qe->moh, NULL);
}
- if (qe->parent->eventwhencalled) {
- char vars[2048];
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when an agent is notified of a member in the queue and fails to answer.</synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentCalled']/managerEventInstance/syntax/parameter[@name='Variable'])" />
- <parameter name="Member">
- <para>The queue member's channel technology or location.</para>
- </parameter>
- <parameter name="RingTime">
- <para>The time the agent was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
- </parameter>
- </syntax>
- <see-also>
- <ref type="managerEvent">AgentCalled</ref>
- </see-also>
- </managerEventInstance>
- ***/
- manager_event(EVENT_FLAG_AGENT, "AgentRingNoAnswer",
- "Queue: %s\r\n"
- "Uniqueid: %s\r\n"
- "Channel: %s\r\n"
- "Member: %s\r\n"
- "MemberName: %s\r\n"
- "RingTime: %d\r\n"
- "%s",
- qe->parent->name,
- ast_channel_uniqueid(qe->chan),
- ast_channel_name(qe->chan),
- interface,
- membername,
- rnatime,
- qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
- }
+ blob = ast_json_pack("{s: s, s: s, s: s, s: i}",
+ "Queue", qe->parent->name,
+ "Interface", interface,
+ "MemberName", membername,
+ "RingTime", rnatime);
+ queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_ringnoanswer_type(), blob);
+
ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), membername, "RINGNOANSWER", "%d", rnatime);
if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && autopause) {
if (qe->parent->autopausedelay > 0) {
@@ -4411,7 +4612,7 @@
do_hang(o);
endtime = (long) time(NULL);
endtime -= starttime;
- rna(endtime * 1000, qe, on, membername, qe->parent->autopausebusy);
+ rna(endtime * 1000, qe, o->chan, on, membername, qe->parent->autopausebusy);
if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
if (qe->parent->timeoutrestart) {
start_time_tv = ast_tvnow();
@@ -4432,7 +4633,7 @@
[... 749 lines stripped ...]
More information about the asterisk-commits
mailing list