app_queue.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief True call queues with optional send URL on answer
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  *
00025  * \par Development notes
00026  * \note 2004-11-25: Persistent Dynamic Members added by:
00027  *             NetNation Communications (www.netnation.com)
00028  *             Kevin Lindsay <kevinl@netnation.com>
00029  *
00030  *             Each dynamic agent in each queue is now stored in the astdb.
00031  *             When asterisk is restarted, each agent will be automatically
00032  *             readded into their recorded queues. This feature can be
00033  *             configured with the 'persistent_members=<1|0>' setting in the
00034  *             '[general]' category in queues.conf. The default is on.
00035  *
00036  * \note 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
00037  *
00038  * \note These features added by David C. Troy <dave@toad.net>:
00039  *    - Per-queue holdtime calculation
00040  *    - Estimated holdtime announcement
00041  *    - Position announcement
00042  *    - Abandoned/completed call counters
00043  *    - Failout timer passed as optional app parameter
00044  *    - Optional monitoring of calls, started when call is answered
00045  *
00046  * Patch Version 1.07 2003-12-24 01
00047  *
00048  * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
00049  * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
00050  *
00051  * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
00052  * by Matthew Enger <m.enger@xi.com.au>
00053  *
00054  * \ingroup applications
00055  */
00056 
00057 /*! \li \ref app_queues.c uses configuration file \ref queues.conf
00058  * \addtogroup configuration_file
00059  */
00060 
00061 /*! \page queues.conf queues.conf
00062  * \verbinclude queues.conf.sample
00063  */
00064 
00065 /*** MODULEINFO
00066    <use type="module">res_monitor</use>
00067    <support_level>core</support_level>
00068  ***/
00069 
00070 #include "asterisk.h"
00071 
00072 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 434450 $")
00073 
00074 #include <sys/time.h>
00075 #include <sys/signal.h>
00076 #include <netinet/in.h>
00077 #include <ctype.h>
00078 
00079 #include "asterisk/lock.h"
00080 #include "asterisk/file.h"
00081 #include "asterisk/channel.h"
00082 #include "asterisk/pbx.h"
00083 #include "asterisk/app.h"
00084 #include "asterisk/linkedlists.h"
00085 #include "asterisk/module.h"
00086 #include "asterisk/translate.h"
00087 #include "asterisk/say.h"
00088 #include "asterisk/features.h"
00089 #include "asterisk/musiconhold.h"
00090 #include "asterisk/cli.h"
00091 #include "asterisk/manager.h"
00092 #include "asterisk/config.h"
00093 #include "asterisk/monitor.h"
00094 #include "asterisk/utils.h"
00095 #include "asterisk/causes.h"
00096 #include "asterisk/astdb.h"
00097 #include "asterisk/devicestate.h"
00098 #include "asterisk/stringfields.h"
00099 #include "asterisk/astobj2.h"
00100 #include "asterisk/strings.h"
00101 #include "asterisk/global_datastores.h"
00102 #include "asterisk/taskprocessor.h"
00103 #include "asterisk/aoc.h"
00104 #include "asterisk/callerid.h"
00105 #include "asterisk/data.h"
00106 #include "asterisk/term.h"
00107 #include "asterisk/dial.h"
00108 #include "asterisk/stasis_channels.h"
00109 #include "asterisk/stasis_message_router.h"
00110 #include "asterisk/bridge_after.h"
00111 #include "asterisk/stasis_bridges.h"
00112 #include "asterisk/core_local.h"
00113 #include "asterisk/mixmonitor.h"
00114 #include "asterisk/core_unreal.h"
00115 #include "asterisk/bridge_basic.h"
00116 
00117 /*!
00118  * \par Please read before modifying this file.
00119  * There are three locks which are regularly used
00120  * throughout this file, the queue list lock, the lock
00121  * for each individual queue, and the interface list lock.
00122  * Please be extra careful to always lock in the following order
00123  * 1) queue list lock
00124  * 2) individual queue lock
00125  * 3) interface list lock
00126  * This order has sort of "evolved" over the lifetime of this
00127  * application, but it is now in place this way, so please adhere
00128  * to this order!
00129  */
00130 
00131 /*** DOCUMENTATION
00132    <application name="Queue" language="en_US">
00133       <synopsis>
00134          Queue a call for a call queue.
00135       </synopsis>
00136       <syntax>
00137          <parameter name="queuename" required="true" />
00138          <parameter name="options">
00139             <optionlist>
00140                <option name="C">
00141                   <para>Mark all calls as "answered elsewhere" when cancelled.</para>
00142                </option>
00143                <option name="c">
00144                   <para>Continue in the dialplan if the callee hangs up.</para>
00145                </option>
00146                <option name="d">
00147                   <para>data-quality (modem) call (minimum delay).</para>
00148                </option>
00149                <option name="F" argsep="^">
00150                   <argument name="context" required="false" />
00151                   <argument name="exten" required="false" />
00152                   <argument name="priority" required="true" />
00153                   <para>When the caller hangs up, transfer the <emphasis>called member</emphasis>
00154                   to the specified destination and <emphasis>start</emphasis> execution at that location.</para>
00155                   <note>
00156                      <para>Any channel variables you want the called channel to inherit from the caller channel must be
00157                      prefixed with one or two underbars ('_').</para>
00158                   </note>
00159                </option>
00160                <option name="F">
00161                   <para>When the caller hangs up, transfer the <emphasis>called member</emphasis> to the next priority of
00162                   the current extension and <emphasis>start</emphasis> execution at that location.</para>
00163                   <note>
00164                      <para>Any channel variables you want the called channel to inherit from the caller channel must be
00165                      prefixed with one or two underbars ('_').</para>
00166                   </note>
00167                   <note>
00168                      <para>Using this option from a Macro() or GoSub() might not make sense as there would be no return points.</para>
00169                   </note>
00170                </option>
00171                <option name="h">
00172                   <para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
00173                </option>
00174                <option name="H">
00175                   <para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
00176                </option>
00177                <option name="n">
00178                   <para>No retries on the timeout; will exit this application and
00179                   go to the next step.</para>
00180                </option>
00181                <option name="i">
00182                   <para>Ignore call forward requests from queue members and do nothing
00183                   when they are requested.</para>
00184                </option>
00185                <option name="I">
00186                   <para>Asterisk will ignore any connected line update requests or any redirecting party
00187                   update requests it may receive on this dial attempt.</para>
00188                </option>
00189                <option name="r">
00190                   <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
00191                </option>
00192                <option name="R">
00193                   <para>Ring instead of playing MOH when a member channel is actually ringing.</para>
00194                </option>
00195                <option name="t">
00196                   <para>Allow the <emphasis>called</emphasis> user to transfer the calling user.</para>
00197                </option>
00198                <option name="T">
00199                   <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para>
00200                </option>
00201                <option name="w">
00202                   <para>Allow the <emphasis>called</emphasis> user to write the conversation to
00203                   disk via Monitor.</para>
00204                </option>
00205                <option name="W">
00206                   <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
00207                   disk via Monitor.</para>
00208                </option>
00209                <option name="k">
00210                   <para>Allow the <emphasis>called</emphasis> party to enable parking of the call by sending
00211                   the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
00212                </option>
00213                <option name="K">
00214                   <para>Allow the <emphasis>calling</emphasis> party to enable parking of the call by sending
00215                   the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
00216                </option>
00217                <option name="x">
00218                   <para>Allow the <emphasis>called</emphasis> user to write the conversation
00219                   to disk via MixMonitor.</para>
00220                </option>
00221                <option name="X">
00222                   <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
00223                   disk via MixMonitor.</para>
00224                </option>
00225             </optionlist>
00226          </parameter>
00227          <parameter name="URL">
00228             <para><replaceable>URL</replaceable> will be sent to the called party if the channel supports it.</para>
00229          </parameter>
00230          <parameter name="announceoverride" />
00231          <parameter name="timeout">
00232             <para>Will cause the queue to fail out after a specified number of
00233             seconds, checked between each <filename>queues.conf</filename> <replaceable>timeout</replaceable> and
00234             <replaceable>retry</replaceable> cycle.</para>
00235          </parameter>
00236          <parameter name="AGI">
00237             <para>Will setup an AGI script to be executed on the calling party's channel once they are
00238             connected to a queue member.</para>
00239          </parameter>
00240          <parameter name="macro">
00241             <para>Will run a macro on the called party's channel (the queue member) once the parties are connected.</para>
00242          </parameter>
00243          <parameter name="gosub">
00244             <para>Will run a gosub on the called party's channel (the queue member) once the parties are connected.</para>
00245          </parameter>
00246          <parameter name="rule">
00247             <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
00248          </parameter>
00249          <parameter name="position">
00250             <para>Attempt to enter the caller into the queue at the numerical position specified. <literal>1</literal>
00251             would attempt to enter the caller at the head of the queue, and <literal>3</literal> would attempt to place
00252             the caller third in the queue.</para>
00253          </parameter>
00254       </syntax>
00255       <description>
00256          <para>In addition to transferring the call, a call may be parked and then picked
00257          up by another user.</para>
00258          <para>This application will return to the dialplan if the queue does not exist, or
00259          any of the join options cause the caller to not enter the queue.</para>
00260          <para>This application does not automatically answer and should be preceeded
00261          by an application such as Answer(), Progress(), or Ringing().</para>
00262          <para>This application sets the following channel variable upon completion:</para>
00263          <variablelist>
00264             <variable name="QUEUESTATUS">
00265                <para>The status of the call as a text string.</para>
00266                <value name="TIMEOUT" />
00267                <value name="FULL" />
00268                <value name="JOINEMPTY" />
00269                <value name="LEAVEEMPTY" />
00270                <value name="JOINUNAVAIL" />
00271                <value name="LEAVEUNAVAIL" />
00272                <value name="CONTINUE" />
00273             </variable>
00274          </variablelist>
00275       </description>
00276       <see-also>
00277          <ref type="application">Queue</ref>
00278          <ref type="application">QueueLog</ref>
00279          <ref type="application">AddQueueMember</ref>
00280          <ref type="application">RemoveQueueMember</ref>
00281          <ref type="application">PauseQueueMember</ref>
00282          <ref type="application">UnpauseQueueMember</ref>
00283          <ref type="function">QUEUE_VARIABLES</ref>
00284          <ref type="function">QUEUE_MEMBER</ref>
00285          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00286          <ref type="function">QUEUE_EXISTS</ref>
00287          <ref type="function">QUEUE_GET_CHANNEL</ref>
00288          <ref type="function">QUEUE_WAITING_COUNT</ref>
00289          <ref type="function">QUEUE_MEMBER_LIST</ref>
00290          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00291       </see-also>
00292    </application>
00293    <application name="AddQueueMember" language="en_US">
00294       <synopsis>
00295          Dynamically adds queue members.
00296       </synopsis>
00297       <syntax>
00298          <parameter name="queuename" required="true" />
00299          <parameter name="interface" />
00300          <parameter name="penalty" />
00301          <parameter name="options" />
00302          <parameter name="membername" />
00303          <parameter name="stateinterface" />
00304       </syntax>
00305       <description>
00306          <para>Dynamically adds interface to an existing queue. If the interface is
00307          already in the queue it will return an error.</para>
00308          <para>This application sets the following channel variable upon completion:</para>
00309          <variablelist>
00310             <variable name="AQMSTATUS">
00311                <para>The status of the attempt to add a queue member as a text string.</para>
00312                <value name="ADDED" />
00313                <value name="MEMBERALREADY" />
00314                <value name="NOSUCHQUEUE" />
00315             </variable>
00316          </variablelist>
00317       </description>
00318       <see-also>
00319          <ref type="application">Queue</ref>
00320          <ref type="application">QueueLog</ref>
00321          <ref type="application">AddQueueMember</ref>
00322          <ref type="application">RemoveQueueMember</ref>
00323          <ref type="application">PauseQueueMember</ref>
00324          <ref type="application">UnpauseQueueMember</ref>
00325          <ref type="function">QUEUE_VARIABLES</ref>
00326          <ref type="function">QUEUE_MEMBER</ref>
00327          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00328          <ref type="function">QUEUE_EXISTS</ref>
00329          <ref type="function">QUEUE_GET_CHANNEL</ref>
00330          <ref type="function">QUEUE_WAITING_COUNT</ref>
00331          <ref type="function">QUEUE_MEMBER_LIST</ref>
00332          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00333       </see-also>
00334    </application>
00335    <application name="RemoveQueueMember" language="en_US">
00336       <synopsis>
00337          Dynamically removes queue members.
00338       </synopsis>
00339       <syntax>
00340          <parameter name="queuename" required="true" />
00341          <parameter name="interface" />
00342       </syntax>
00343       <description>
00344          <para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
00345          <para>This application sets the following channel variable upon completion:</para>
00346          <variablelist>
00347             <variable name="RQMSTATUS">
00348                <value name="REMOVED" />
00349                <value name="NOTINQUEUE" />
00350                <value name="NOSUCHQUEUE" />
00351                <value name="NOTDYNAMIC" />
00352             </variable>
00353          </variablelist>
00354          <para>Example: RemoveQueueMember(techsupport,SIP/3000)</para>
00355       </description>
00356       <see-also>
00357          <ref type="application">Queue</ref>
00358          <ref type="application">QueueLog</ref>
00359          <ref type="application">AddQueueMember</ref>
00360          <ref type="application">RemoveQueueMember</ref>
00361          <ref type="application">PauseQueueMember</ref>
00362          <ref type="application">UnpauseQueueMember</ref>
00363          <ref type="function">QUEUE_VARIABLES</ref>
00364          <ref type="function">QUEUE_MEMBER</ref>
00365          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00366          <ref type="function">QUEUE_EXISTS</ref>
00367          <ref type="function">QUEUE_GET_CHANNEL</ref>
00368          <ref type="function">QUEUE_WAITING_COUNT</ref>
00369          <ref type="function">QUEUE_MEMBER_LIST</ref>
00370          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00371       </see-also>
00372    </application>
00373    <application name="PauseQueueMember" language="en_US">
00374       <synopsis>
00375          Pauses a queue member.
00376       </synopsis>
00377       <syntax>
00378          <parameter name="queuename" />
00379          <parameter name="interface" required="true" />
00380          <parameter name="options" />
00381          <parameter name="reason">
00382             <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
00383          </parameter>
00384       </syntax>
00385       <description>
00386          <para>Pauses (blocks calls for) a queue member. The given interface will be paused in the given queue.
00387          This prevents any calls from being sent from the queue to the interface until it is
00388          unpaused with UnpauseQueueMember or the manager interface.  If no queuename is given,
00389          the interface is paused in every queue it is a member of. The application will fail if the
00390          interface is not found.</para>
00391          <para>This application sets the following channel variable upon completion:</para>
00392          <variablelist>
00393             <variable name="PQMSTATUS">
00394                <para>The status of the attempt to pause a queue member as a text string.</para>
00395                <value name="PAUSED" />
00396                <value name="NOTFOUND" />
00397             </variable>
00398          </variablelist>
00399          <para>Example: PauseQueueMember(,SIP/3000)</para>
00400       </description>
00401       <see-also>
00402          <ref type="application">Queue</ref>
00403          <ref type="application">QueueLog</ref>
00404          <ref type="application">AddQueueMember</ref>
00405          <ref type="application">RemoveQueueMember</ref>
00406          <ref type="application">PauseQueueMember</ref>
00407          <ref type="application">UnpauseQueueMember</ref>
00408          <ref type="function">QUEUE_VARIABLES</ref>
00409          <ref type="function">QUEUE_MEMBER</ref>
00410          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00411          <ref type="function">QUEUE_EXISTS</ref>
00412          <ref type="function">QUEUE_GET_CHANNEL</ref>
00413          <ref type="function">QUEUE_WAITING_COUNT</ref>
00414          <ref type="function">QUEUE_MEMBER_LIST</ref>
00415          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00416       </see-also>
00417    </application>
00418    <application name="UnpauseQueueMember" language="en_US">
00419       <synopsis>
00420          Unpauses a queue member.
00421       </synopsis>
00422       <syntax>
00423          <parameter name="queuename" />
00424          <parameter name="interface" required="true" />
00425          <parameter name="options" />
00426          <parameter name="reason">
00427             <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
00428          </parameter>
00429       </syntax>
00430       <description>
00431          <para>Unpauses (resumes calls to) a queue member. This is the counterpart to <literal>PauseQueueMember()</literal>
00432          and operates exactly the same way, except it unpauses instead of pausing the given interface.</para>
00433          <para>This application sets the following channel variable upon completion:</para>
00434          <variablelist>
00435             <variable name="UPQMSTATUS">
00436                <para>The status of the attempt to unpause a queue member as a text string.</para>
00437                <value name="UNPAUSED" />
00438                <value name="NOTFOUND" />
00439             </variable>
00440          </variablelist>
00441          <para>Example: UnpauseQueueMember(,SIP/3000)</para>
00442       </description>
00443       <see-also>
00444          <ref type="application">Queue</ref>
00445          <ref type="application">QueueLog</ref>
00446          <ref type="application">AddQueueMember</ref>
00447          <ref type="application">RemoveQueueMember</ref>
00448          <ref type="application">PauseQueueMember</ref>
00449          <ref type="application">UnpauseQueueMember</ref>
00450          <ref type="function">QUEUE_VARIABLES</ref>
00451          <ref type="function">QUEUE_MEMBER</ref>
00452          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00453          <ref type="function">QUEUE_EXISTS</ref>
00454          <ref type="function">QUEUE_GET_CHANNEL</ref>
00455          <ref type="function">QUEUE_WAITING_COUNT</ref>
00456          <ref type="function">QUEUE_MEMBER_LIST</ref>
00457          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00458       </see-also>
00459    </application>
00460    <application name="QueueLog" language="en_US">
00461       <synopsis>
00462          Writes to the queue_log file.
00463       </synopsis>
00464       <syntax>
00465          <parameter name="queuename" required="true" />
00466          <parameter name="uniqueid" required="true" />
00467          <parameter name="agent" required="true" />
00468          <parameter name="event" required="true" />
00469          <parameter name="additionalinfo" />
00470       </syntax>
00471       <description>
00472          <para>Allows you to write your own events into the queue log.</para>
00473          <para>Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)</para>
00474       </description>
00475       <see-also>
00476          <ref type="application">Queue</ref>
00477          <ref type="application">QueueLog</ref>
00478          <ref type="application">AddQueueMember</ref>
00479          <ref type="application">RemoveQueueMember</ref>
00480          <ref type="application">PauseQueueMember</ref>
00481          <ref type="application">UnpauseQueueMember</ref>
00482          <ref type="function">QUEUE_VARIABLES</ref>
00483          <ref type="function">QUEUE_MEMBER</ref>
00484          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00485          <ref type="function">QUEUE_EXISTS</ref>
00486          <ref type="function">QUEUE_GET_CHANNEL</ref>
00487          <ref type="function">QUEUE_WAITING_COUNT</ref>
00488          <ref type="function">QUEUE_MEMBER_LIST</ref>
00489          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00490       </see-also>
00491    </application>
00492    <function name="QUEUE_VARIABLES" language="en_US">
00493       <synopsis>
00494          Return Queue information in variables.
00495       </synopsis>
00496       <syntax>
00497          <parameter name="queuename" required="true">
00498             <enumlist>
00499                <enum name="QUEUEMAX">
00500                   <para>Maxmimum number of calls allowed.</para>
00501                </enum>
00502                <enum name="QUEUESTRATEGY">
00503                   <para>The strategy of the queue.</para>
00504                </enum>
00505                <enum name="QUEUECALLS">
00506                   <para>Number of calls currently in the queue.</para>
00507                </enum>
00508                <enum name="QUEUEHOLDTIME">
00509                   <para>Current average hold time.</para>
00510                </enum>
00511                <enum name="QUEUECOMPLETED">
00512                   <para>Number of completed calls for the queue.</para>
00513                </enum>
00514                <enum name="QUEUEABANDONED">
00515                   <para>Number of abandoned calls.</para>
00516                </enum>
00517                <enum name="QUEUESRVLEVEL">
00518                   <para>Queue service level.</para>
00519                </enum>
00520                <enum name="QUEUESRVLEVELPERF">
00521                   <para>Current service level performance.</para>
00522                </enum>
00523             </enumlist>
00524          </parameter>
00525       </syntax>
00526       <description>
00527          <para>Makes the following queue variables available.</para>
00528          <para>Returns <literal>0</literal> if queue is found and setqueuevar is defined, <literal>-1</literal> otherwise.</para>
00529       </description>
00530       <see-also>
00531          <ref type="application">Queue</ref>
00532          <ref type="application">QueueLog</ref>
00533          <ref type="application">AddQueueMember</ref>
00534          <ref type="application">RemoveQueueMember</ref>
00535          <ref type="application">PauseQueueMember</ref>
00536          <ref type="application">UnpauseQueueMember</ref>
00537          <ref type="function">QUEUE_VARIABLES</ref>
00538          <ref type="function">QUEUE_MEMBER</ref>
00539          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00540          <ref type="function">QUEUE_EXISTS</ref>
00541          <ref type="function">QUEUE_GET_CHANNEL</ref>
00542          <ref type="function">QUEUE_WAITING_COUNT</ref>
00543          <ref type="function">QUEUE_MEMBER_LIST</ref>
00544          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00545       </see-also>
00546    </function>
00547    <function name="QUEUE_MEMBER" language="en_US">
00548       <synopsis>
00549          Count number of members answering a queue.
00550       </synopsis>
00551       <syntax>
00552          <parameter name="queuename" required="true" />
00553          <parameter name="option" required="true">
00554             <enumlist>
00555                <enum name="logged">
00556                   <para>Returns the number of logged-in members for the specified queue.</para>
00557                </enum>
00558                <enum name="free">
00559                   <para>Returns the number of logged-in members for the specified queue that either can take calls or are currently wrapping up after a previous call.</para>
00560                </enum>
00561                <enum name="ready">
00562                   <para>Returns the number of logged-in members for the specified queue that are immediately available to answer a call.</para>
00563                </enum>
00564                <enum name="count">
00565                   <para>Returns the total number of members for the specified queue.</para>
00566                </enum>
00567                <enum name="penalty">
00568                   <para>Gets or sets queue member penalty.</para>
00569                </enum>
00570                <enum name="paused">
00571                   <para>Gets or sets queue member paused status.</para>
00572                </enum>
00573                <enum name="ringinuse">
00574                   <para>Gets or sets queue member ringinuse.</para>
00575                </enum>
00576             </enumlist>
00577          </parameter>
00578          <parameter name="interface" required="false" />
00579       </syntax>
00580       <description>
00581          <para>Allows access to queue counts [R] and member information [R/W].</para>
00582          <para>
00583             <replaceable>queuename</replaceable> is required for all operations
00584             <replaceable>interface</replaceable> is required for all member operations.
00585          </para>
00586       </description>
00587       <see-also>
00588          <ref type="application">Queue</ref>
00589          <ref type="application">QueueLog</ref>
00590          <ref type="application">AddQueueMember</ref>
00591          <ref type="application">RemoveQueueMember</ref>
00592          <ref type="application">PauseQueueMember</ref>
00593          <ref type="application">UnpauseQueueMember</ref>
00594          <ref type="function">QUEUE_VARIABLES</ref>
00595          <ref type="function">QUEUE_MEMBER</ref>
00596          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00597          <ref type="function">QUEUE_EXISTS</ref>
00598          <ref type="function">QUEUE_GET_CHANNEL</ref>
00599          <ref type="function">QUEUE_WAITING_COUNT</ref>
00600          <ref type="function">QUEUE_MEMBER_LIST</ref>
00601          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00602       </see-also>
00603    </function>
00604    <function name="QUEUE_MEMBER_COUNT" language="en_US">
00605       <synopsis>
00606          Count number of members answering a queue.
00607       </synopsis>
00608       <syntax>
00609          <parameter name="queuename" required="true" />
00610       </syntax>
00611       <description>
00612          <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
00613          <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
00614       </description>
00615       <see-also>
00616          <ref type="application">Queue</ref>
00617          <ref type="application">QueueLog</ref>
00618          <ref type="application">AddQueueMember</ref>
00619          <ref type="application">RemoveQueueMember</ref>
00620          <ref type="application">PauseQueueMember</ref>
00621          <ref type="application">UnpauseQueueMember</ref>
00622          <ref type="function">QUEUE_VARIABLES</ref>
00623          <ref type="function">QUEUE_MEMBER</ref>
00624          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00625          <ref type="function">QUEUE_EXISTS</ref>
00626          <ref type="function">QUEUE_GET_CHANNEL</ref>
00627          <ref type="function">QUEUE_WAITING_COUNT</ref>
00628          <ref type="function">QUEUE_MEMBER_LIST</ref>
00629          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00630       </see-also>
00631    </function>
00632    <function name="QUEUE_EXISTS" language="en_US">
00633       <synopsis>
00634          Check if a named queue exists on this server
00635       </synopsis>
00636       <syntax>
00637          <parameter name="queuename" />
00638       </syntax>
00639       <description>
00640          <para>Returns 1 if the specified queue exists, 0 if it does not</para>
00641       </description>
00642       <see-also>
00643          <ref type="application">Queue</ref>
00644          <ref type="application">QueueLog</ref>
00645          <ref type="application">AddQueueMember</ref>
00646          <ref type="application">RemoveQueueMember</ref>
00647          <ref type="application">PauseQueueMember</ref>
00648          <ref type="application">UnpauseQueueMember</ref>
00649          <ref type="function">QUEUE_VARIABLES</ref>
00650          <ref type="function">QUEUE_MEMBER</ref>
00651          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00652          <ref type="function">QUEUE_EXISTS</ref>
00653          <ref type="function">QUEUE_GET_CHANNEL</ref>
00654          <ref type="function">QUEUE_WAITING_COUNT</ref>
00655          <ref type="function">QUEUE_MEMBER_LIST</ref>
00656          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00657       </see-also>
00658    </function>
00659    <function name="QUEUE_GET_CHANNEL" language="en_US">
00660       <synopsis>
00661          Return caller at the specified position in a queue.
00662       </synopsis>
00663       <syntax>
00664          <parameter name="queuename" required="true" />
00665          <parameter name="position" />
00666       </syntax>
00667       <description>
00668          <para>Returns the caller channel at <replaceable>position</replaceable> in the specified <replaceable>queuename</replaceable>.</para>
00669          <para>If <replaceable>position</replaceable> is unspecified the first channel is returned.</para>
00670       </description>
00671       <see-also>
00672          <ref type="application">Queue</ref>
00673          <ref type="application">QueueLog</ref>
00674          <ref type="application">AddQueueMember</ref>
00675          <ref type="application">RemoveQueueMember</ref>
00676          <ref type="application">PauseQueueMember</ref>
00677          <ref type="application">UnpauseQueueMember</ref>
00678          <ref type="function">QUEUE_VARIABLES</ref>
00679          <ref type="function">QUEUE_MEMBER</ref>
00680          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00681          <ref type="function">QUEUE_EXISTS</ref>
00682          <ref type="function">QUEUE_WAITING_COUNT</ref>
00683          <ref type="function">QUEUE_MEMBER_LIST</ref>
00684          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00685       </see-also>
00686    </function>
00687    <function name="QUEUE_WAITING_COUNT" language="en_US">
00688       <synopsis>
00689          Count number of calls currently waiting in a queue.
00690       </synopsis>
00691       <syntax>
00692          <parameter name="queuename" />
00693       </syntax>
00694       <description>
00695          <para>Returns the number of callers currently waiting in the specified <replaceable>queuename</replaceable>.</para>
00696       </description>
00697       <see-also>
00698          <ref type="application">Queue</ref>
00699          <ref type="application">QueueLog</ref>
00700          <ref type="application">AddQueueMember</ref>
00701          <ref type="application">RemoveQueueMember</ref>
00702          <ref type="application">PauseQueueMember</ref>
00703          <ref type="application">UnpauseQueueMember</ref>
00704          <ref type="function">QUEUE_VARIABLES</ref>
00705          <ref type="function">QUEUE_MEMBER</ref>
00706          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00707          <ref type="function">QUEUE_EXISTS</ref>
00708          <ref type="function">QUEUE_GET_CHANNEL</ref>
00709          <ref type="function">QUEUE_WAITING_COUNT</ref>
00710          <ref type="function">QUEUE_MEMBER_LIST</ref>
00711          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00712       </see-also>
00713    </function>
00714    <function name="QUEUE_MEMBER_LIST" language="en_US">
00715       <synopsis>
00716          Returns a list of interfaces on a queue.
00717       </synopsis>
00718       <syntax>
00719          <parameter name="queuename" required="true" />
00720       </syntax>
00721       <description>
00722          <para>Returns a comma-separated list of members associated with the specified <replaceable>queuename</replaceable>.</para>
00723       </description>
00724       <see-also>
00725          <ref type="application">Queue</ref>
00726          <ref type="application">QueueLog</ref>
00727          <ref type="application">AddQueueMember</ref>
00728          <ref type="application">RemoveQueueMember</ref>
00729          <ref type="application">PauseQueueMember</ref>
00730          <ref type="application">UnpauseQueueMember</ref>
00731          <ref type="function">QUEUE_VARIABLES</ref>
00732          <ref type="function">QUEUE_MEMBER</ref>
00733          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00734          <ref type="function">QUEUE_EXISTS</ref>
00735          <ref type="function">QUEUE_GET_CHANNEL</ref>
00736          <ref type="function">QUEUE_WAITING_COUNT</ref>
00737          <ref type="function">QUEUE_MEMBER_LIST</ref>
00738          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00739       </see-also>
00740    </function>
00741    <function name="QUEUE_MEMBER_PENALTY" language="en_US">
00742       <synopsis>
00743          Gets or sets queue members penalty.
00744       </synopsis>
00745       <syntax>
00746          <parameter name="queuename" required="true" />
00747          <parameter name="interface" required="true" />
00748       </syntax>
00749       <description>
00750          <para>Gets or sets queue members penalty.</para>
00751          <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
00752       </description>
00753       <see-also>
00754          <ref type="application">Queue</ref>
00755          <ref type="application">QueueLog</ref>
00756          <ref type="application">AddQueueMember</ref>
00757          <ref type="application">RemoveQueueMember</ref>
00758          <ref type="application">PauseQueueMember</ref>
00759          <ref type="application">UnpauseQueueMember</ref>
00760          <ref type="function">QUEUE_VARIABLES</ref>
00761          <ref type="function">QUEUE_MEMBER</ref>
00762          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00763          <ref type="function">QUEUE_EXISTS</ref>
00764          <ref type="function">QUEUE_GET_CHANNEL</ref>
00765          <ref type="function">QUEUE_WAITING_COUNT</ref>
00766          <ref type="function">QUEUE_MEMBER_LIST</ref>
00767          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00768       </see-also>
00769    </function>
00770    <manager name="Queues" language="en_US">
00771       <synopsis>
00772          Queues.
00773       </synopsis>
00774       <syntax>
00775       </syntax>
00776       <description>
00777          <para>Show queues information.</para>
00778       </description>
00779    </manager>
00780    <manager name="QueueStatus" language="en_US">
00781       <synopsis>
00782          Show queue status.
00783       </synopsis>
00784       <syntax>
00785          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00786          <parameter name="Queue">
00787             <para>Limit the response to the status of the specified queue.</para>
00788          </parameter>
00789          <parameter name="Member">
00790             <para>Limit the response to the status of the specified member.</para>
00791          </parameter>
00792       </syntax>
00793       <description>
00794          <para>Check the status of one or more queues.</para>
00795       </description>
00796    </manager>
00797    <manager name="QueueSummary" language="en_US">
00798       <synopsis>
00799          Show queue summary.
00800       </synopsis>
00801       <syntax>
00802          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00803          <parameter name="Queue">
00804             <para>Queue for which the summary is requested.</para>
00805          </parameter>
00806       </syntax>
00807       <description>
00808          <para>Request the manager to send a QueueSummary event.</para>
00809       </description>
00810    </manager>
00811    <manager name="QueueAdd" language="en_US">
00812       <synopsis>
00813          Add interface to queue.
00814       </synopsis>
00815       <syntax>
00816          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00817          <parameter name="Queue" required="true">
00818             <para>Queue's name.</para>
00819          </parameter>
00820          <parameter name="Interface" required="true">
00821             <para>The name of the interface (tech/name) to add to the queue.</para>
00822          </parameter>
00823          <parameter name="Penalty">
00824             <para>A penalty (number) to apply to this member. Asterisk will distribute calls to members with higher penalties only after attempting to distribute calls to those with lower penalty.</para>
00825          </parameter>
00826          <parameter name="Paused">
00827             <para>To pause or not the member initially (true/false or 1/0).</para>
00828          </parameter>
00829          <parameter name="MemberName">
00830             <para>Text alias for the interface.</para>
00831          </parameter>
00832          <parameter name="StateInterface" />
00833       </syntax>
00834       <description>
00835       </description>
00836    </manager>
00837    <manager name="QueueRemove" language="en_US">
00838       <synopsis>
00839          Remove interface from queue.
00840       </synopsis>
00841       <syntax>
00842          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00843          <parameter name="Queue" required="true">
00844             <para>The name of the queue to take action on.</para>
00845          </parameter>
00846          <parameter name="Interface" required="true">
00847             <para>The interface (tech/name) to remove from queue.</para>
00848          </parameter>
00849       </syntax>
00850       <description>
00851       </description>
00852    </manager>
00853    <manager name="QueuePause" language="en_US">
00854       <synopsis>
00855          Makes a queue member temporarily unavailable.
00856       </synopsis>
00857       <syntax>
00858          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00859          <parameter name="Interface" required="true">
00860             <para>The name of the interface (tech/name) to pause or unpause.</para>
00861          </parameter>
00862          <parameter name="Paused" required="true">
00863             <para>Pause or unpause the interface. Set to 'true' to pause the member or 'false' to unpause.</para>
00864          </parameter>
00865          <parameter name="Queue">
00866             <para>The name of the queue in which to pause or unpause this member. If not specified, the member will be paused or unpaused in all the queues it is a member of.</para>
00867          </parameter>
00868          <parameter name="Reason">
00869             <para>Text description, returned in the event QueueMemberPaused.</para>
00870          </parameter>
00871       </syntax>
00872       <description>
00873          <para>Pause or unpause a member in a queue.</para>
00874       </description>
00875    </manager>
00876    <manager name="QueueLog" language="en_US">
00877       <synopsis>
00878          Adds custom entry in queue_log.
00879       </synopsis>
00880       <syntax>
00881          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00882          <parameter name="Queue" required="true" />
00883          <parameter name="Event" required="true" />
00884          <parameter name="Uniqueid" />
00885          <parameter name="Interface" />
00886          <parameter name="Message" />
00887       </syntax>
00888       <description>
00889       </description>
00890    </manager>
00891    <manager name="QueuePenalty" language="en_US">
00892       <synopsis>
00893          Set the penalty for a queue member.
00894       </synopsis>
00895       <syntax>
00896          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00897          <parameter name="Interface" required="true">
00898             <para>The interface (tech/name) of the member whose penalty to change.</para>
00899          </parameter>
00900          <parameter name="Penalty" required="true">
00901             <para>The new penalty (number) for the member. Must be nonnegative.</para>
00902          </parameter>
00903          <parameter name="Queue">
00904             <para>If specified, only set the penalty for the member of this queue. Otherwise, set the penalty for the member in all queues to which the member belongs.</para>
00905          </parameter>
00906       </syntax>
00907       <description>
00908          <para>Change the penalty of a queue member</para>
00909       </description>
00910    </manager>
00911    <manager name="QueueMemberRingInUse" language="en_US">
00912       <synopsis>
00913          Set the ringinuse value for a queue member.
00914       </synopsis>
00915       <syntax>
00916          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00917          <parameter name="Interface" required="true" />
00918          <parameter name="RingInUse" required="true" />
00919          <parameter name="Queue" />
00920       </syntax>
00921       <description>
00922       </description>
00923    </manager>
00924    <manager name="QueueRule" language="en_US">
00925       <synopsis>
00926          Queue Rules.
00927       </synopsis>
00928       <syntax>
00929          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00930          <parameter name="Rule">
00931             <para>The name of the rule in queuerules.conf whose contents to list.</para>
00932          </parameter>
00933       </syntax>
00934       <description>
00935          <para>List queue rules defined in queuerules.conf</para>
00936       </description>
00937    </manager>
00938    <manager name="QueueReload" language="en_US">
00939       <synopsis>
00940          Reload a queue, queues, or any sub-section of a queue or queues.
00941       </synopsis>
00942       <syntax>
00943          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00944          <parameter name="Queue">
00945             <para>The name of the queue to take action on. If no queue name is specified, then all queues are affected.</para>
00946          </parameter>
00947          <parameter name="Members">
00948             <para>Whether to reload the queue's members.</para>
00949             <enumlist>
00950                <enum name="yes" />
00951                <enum name="no" />
00952             </enumlist>
00953          </parameter>
00954          <parameter name="Rules">
00955             <para>Whether to reload queuerules.conf</para>
00956             <enumlist>
00957                <enum name="yes" />
00958                <enum name="no" />
00959             </enumlist>
00960          </parameter>
00961          <parameter name="Parameters">
00962             <para>Whether to reload the other queue options.</para>
00963             <enumlist>
00964                <enum name="yes" />
00965                <enum name="no" />
00966             </enumlist>
00967          </parameter>
00968       </syntax>
00969       <description>
00970       </description>
00971    </manager>
00972    <manager name="QueueReset" language="en_US">
00973       <synopsis>
00974          Reset queue statistics.
00975       </synopsis>
00976       <syntax>
00977          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00978          <parameter name="Queue">
00979             <para>The name of the queue on which to reset statistics.</para>
00980          </parameter>
00981       </syntax>
00982       <description>
00983          <para>Reset the statistics for a queue.</para>
00984       </description>
00985    </manager>
00986 
00987    <managerEvent language="en_US" name="QueueMemberStatus">
00988       <managerEventInstance class="EVENT_FLAG_AGENT">
00989          <synopsis>Raised when a Queue member's status has changed.</synopsis>
00990          <syntax>
00991             <parameter name="Queue">
00992                <para>The name of the queue.</para>
00993             </parameter>
00994             <parameter name="MemberName">
00995                <para>The name of the queue member.</para>
00996             </parameter>
00997             <parameter name="Interface">
00998                <para>The queue member's channel technology or location.</para>
00999             </parameter>
01000             <parameter name="StateInterface">
01001                <para>Channel technology or location from which to read device state changes.</para>
01002             </parameter>
01003             <parameter name="Membership">
01004                <enumlist>
01005                   <enum name="dynamic"/>
01006                   <enum name="realtime"/>
01007                   <enum name="static"/>
01008                </enumlist>
01009             </parameter>
01010             <parameter name="Penalty">
01011                <para>The penalty associated with the queue member.</para>
01012             </parameter>
01013             <parameter name="CallsTaken">
01014                <para>The number of calls this queue member has serviced.</para>
01015             </parameter>
01016             <parameter name="LastCall">
01017                <para>The time this member last took a call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
01018             </parameter>
01019             <parameter name="Status">
01020                <para>The numeric device state status of the queue member.</para>
01021                <enumlist>
01022                   <enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>
01023                   <enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>
01024                   <enum name="2"><para>AST_DEVICE_INUSE</para></enum>
01025                   <enum name="3"><para>AST_DEVICE_BUSY</para></enum>
01026                   <enum name="4"><para>AST_DEVICE_INVALID</para></enum>
01027                   <enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>
01028                   <enum name="6"><para>AST_DEVICE_RINGING</para></enum>
01029                   <enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>
01030                   <enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>
01031                </enumlist>
01032             </parameter>
01033             <parameter name="Paused">
01034                <enumlist>
01035                   <enum name="0"/>
01036                   <enum name="1"/>
01037                </enumlist>
01038             </parameter>
01039             <parameter name="Ringinuse">
01040                <enumlist>
01041                   <enum name="0"/>
01042                   <enum name="1"/>
01043                </enumlist>
01044             </parameter>
01045          </syntax>
01046       </managerEventInstance>
01047    </managerEvent>
01048    <managerEvent language="en_US" name="QueueMemberAdded">
01049       <managerEventInstance class="EVENT_FLAG_AGENT">
01050          <synopsis>Raised when a member is added to the queue.</synopsis>
01051          <syntax>
01052             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
01053          </syntax>
01054          <see-also>
01055             <ref type="managerEvent">QueueMemberRemoved</ref>
01056             <ref type="application">AddQueueMember</ref>
01057          </see-also>
01058       </managerEventInstance>
01059    </managerEvent>
01060    <managerEvent language="en_US" name="QueueMemberRemoved">
01061       <managerEventInstance class="EVENT_FLAG_AGENT">
01062          <synopsis>Raised when a member is removed from the queue.</synopsis>
01063          <syntax>
01064             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
01065          </syntax>
01066          <see-also>
01067             <ref type="managerEvent">QueueMemberAdded</ref>
01068             <ref type="application">RemoveQueueMember</ref>
01069          </see-also>
01070       </managerEventInstance>
01071    </managerEvent>
01072    <managerEvent language="en_US" name="QueueMemberPause">
01073       <managerEventInstance class="EVENT_FLAG_AGENT">
01074          <synopsis>Raised when a member is paused/unpaused in the queue.</synopsis>
01075          <syntax>
01076             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
01077             <parameter name="Reason">
01078                <para>The reason a member was paused.</para>
01079             </parameter>
01080          </syntax>
01081          <see-also>
01082             <ref type="application">PauseQueueMember</ref>
01083             <ref type="application">UnPauseQueueMember</ref>
01084          </see-also>
01085       </managerEventInstance>
01086    </managerEvent>
01087    <managerEvent language="en_US" name="QueueMemberPenalty">
01088       <managerEventInstance class="EVENT_FLAG_AGENT">
01089          <synopsis>Raised when a member's penalty is changed.</synopsis>
01090          <syntax>
01091             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
01092          </syntax>
01093          <see-also>
01094             <ref type="function">QUEUE_MEMBER</ref>
01095          </see-also>
01096       </managerEventInstance>
01097    </managerEvent>
01098    <managerEvent language="en_US" name="QueueMemberRinginuse">
01099       <managerEventInstance class="EVENT_FLAG_AGENT">
01100          <synopsis>Raised when a member's ringinuse setting is changed.</synopsis>
01101          <syntax>
01102             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
01103          </syntax>
01104          <see-also>
01105             <ref type="function">QUEUE_MEMBER</ref>
01106          </see-also>
01107       </managerEventInstance>
01108    </managerEvent>
01109    <managerEvent language="en_US" name="QueueCallerJoin">
01110       <managerEventInstance class="EVENT_FLAG_AGENT">
01111          <synopsis>Raised when a caller joins a Queue.</synopsis>
01112          <syntax>
01113             <channel_snapshot/>
01114             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
01115             <parameter name="Position">
01116                <para>This channel's current position in the queue.</para>
01117             </parameter>
01118             <parameter name="Count">
01119                <para>The total number of channels in the queue.</para>
01120             </parameter>
01121          </syntax>
01122          <see-also>
01123             <ref type="managerEvent">QueueCallerLeave</ref>
01124             <ref type="application">Queue</ref>
01125          </see-also>
01126       </managerEventInstance>
01127    </managerEvent>
01128    <managerEvent language="en_US" name="QueueCallerLeave">
01129       <managerEventInstance class="EVENT_FLAG_AGENT">
01130          <synopsis>Raised when a caller leaves a Queue.</synopsis>
01131          <syntax>
01132             <channel_snapshot/>
01133             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
01134             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Count'])" />
01135             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
01136          </syntax>
01137          <see-also>
01138             <ref type="managerEvent">QueueCallerJoin</ref>
01139          </see-also>
01140       </managerEventInstance>
01141    </managerEvent>
01142    <managerEvent language="en_US" name="QueueCallerAbandon">
01143       <managerEventInstance class="EVENT_FLAG_AGENT">
01144          <synopsis>Raised when a caller abandons the queue.</synopsis>
01145          <syntax>
01146             <channel_snapshot/>
01147             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
01148             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerJoin']/managerEventInstance/syntax/parameter[@name='Position'])" />
01149             <parameter name="OriginalPosition">
01150                <para>The channel's original position in the queue.</para>
01151             </parameter>
01152             <parameter name="HoldTime">
01153                <para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
01154             </parameter>
01155          </syntax>
01156       </managerEventInstance>
01157    </managerEvent>
01158    <managerEvent language="en_US" name="AgentCalled">
01159       <managerEventInstance class="EVENT_FLAG_AGENT">
01160          <synopsis>Raised when an queue member is notified of a caller in the queue.</synopsis>
01161          <syntax>
01162             <channel_snapshot/>
01163             <channel_snapshot prefix="Dest"/>
01164             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
01165             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
01166             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
01167          </syntax>
01168          <see-also>
01169             <ref type="managerEvent">AgentRingNoAnswer</ref>
01170             <ref type="managerEvent">AgentComplete</ref>
01171             <ref type="managerEvent">AgentConnect</ref>
01172          </see-also>
01173       </managerEventInstance>
01174    </managerEvent>
01175    <managerEvent language="en_US" name="AgentRingNoAnswer">
01176       <managerEventInstance class="EVENT_FLAG_AGENT">
01177          <synopsis>Raised when a queue member is notified of a caller in the queue and fails to answer.</synopsis>
01178          <syntax>
01179             <channel_snapshot/>
01180             <channel_snapshot prefix="Dest"/>
01181             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
01182             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
01183             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
01184             <parameter name="RingTime">
01185                <para>The time the queue member was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
01186             </parameter>
01187          </syntax>
01188          <see-also>
01189             <ref type="managerEvent">AgentCalled</ref>
01190          </see-also>
01191       </managerEventInstance>
01192    </managerEvent>
01193    <managerEvent language="en_US" name="AgentComplete">
01194       <managerEventInstance class="EVENT_FLAG_AGENT">
01195          <synopsis>Raised when a queue member has finished servicing a caller in the queue.</synopsis>
01196          <syntax>
01197             <channel_snapshot/>
01198             <channel_snapshot prefix="Dest"/>
01199             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
01200             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
01201             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
01202             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
01203             <parameter name="TalkTime">
01204                <para>The time the queue member talked with the caller in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
01205             </parameter>
01206             <parameter name="Reason">
01207                <enumlist>
01208                   <enum name="caller"/>
01209                   <enum name="agent"/>
01210                   <enum name="transfer"/>
01211                </enumlist>
01212             </parameter>
01213          </syntax>
01214          <see-also>
01215             <ref type="managerEvent">AgentCalled</ref>
01216             <ref type="managerEvent">AgentConnect</ref>
01217          </see-also>
01218       </managerEventInstance>
01219    </managerEvent>
01220    <managerEvent language="en_US" name="AgentDump">
01221       <managerEventInstance class="EVENT_FLAG_AGENT">
01222          <synopsis>Raised when a queue member hangs up on a caller in the queue.</synopsis>
01223          <syntax>
01224             <channel_snapshot/>
01225             <channel_snapshot prefix="Dest"/>
01226             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
01227             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
01228             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
01229          </syntax>
01230          <see-also>
01231             <ref type="managerEvent">AgentCalled</ref>
01232             <ref type="managerEvent">AgentConnect</ref>
01233          </see-also>
01234       </managerEventInstance>
01235    </managerEvent>
01236    <managerEvent language="en_US" name="AgentConnect">
01237       <managerEventInstance class="EVENT_FLAG_AGENT">
01238          <synopsis>Raised when a queue member answers and is bridged to a caller in the queue.</synopsis>
01239          <syntax>
01240             <channel_snapshot/>
01241             <channel_snapshot prefix="Dest"/>
01242             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
01243             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
01244             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Interface'])" />
01245             <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='RingTime'])" />
01246             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
01247          </syntax>
01248          <see-also>
01249             <ref type="managerEvent">AgentCalled</ref>
01250             <ref type="managerEvent">AgentComplete</ref>
01251             <ref type="managerEvent">AgentDump</ref>
01252          </see-also>
01253       </managerEventInstance>
01254    </managerEvent>
01255  ***/
01256 
01257 enum {
01258    OPT_MARK_AS_ANSWERED =       (1 << 0),
01259    OPT_GO_ON =                  (1 << 1),
01260    OPT_DATA_QUALITY =           (1 << 2),
01261    OPT_CALLEE_GO_ON =           (1 << 3),
01262    OPT_CALLEE_HANGUP =          (1 << 4),
01263    OPT_CALLER_HANGUP =          (1 << 5),
01264    OPT_IGNORE_CALL_FW =         (1 << 6),
01265    OPT_IGNORE_CONNECTEDLINE =   (1 << 7),
01266    OPT_CALLEE_PARK =            (1 << 8),
01267    OPT_CALLER_PARK =            (1 << 9),
01268    OPT_NO_RETRY =               (1 << 10),
01269    OPT_RINGING =                (1 << 11),
01270    OPT_RING_WHEN_RINGING =      (1 << 12),
01271    OPT_CALLEE_TRANSFER =        (1 << 13),
01272    OPT_CALLER_TRANSFER =        (1 << 14),
01273    OPT_CALLEE_AUTOMIXMON =      (1 << 15),
01274    OPT_CALLER_AUTOMIXMON =      (1 << 16),
01275    OPT_CALLEE_AUTOMON =         (1 << 17),
01276    OPT_CALLER_AUTOMON =         (1 << 18),
01277 };
01278 
01279 enum {
01280    OPT_ARG_CALLEE_GO_ON = 0,
01281    /* note: this entry _MUST_ be the last one in the enum */
01282    OPT_ARG_ARRAY_SIZE
01283 };
01284 
01285 AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS
01286    AST_APP_OPTION('C', OPT_MARK_AS_ANSWERED),
01287    AST_APP_OPTION('c', OPT_GO_ON),
01288    AST_APP_OPTION('d', OPT_DATA_QUALITY),
01289    AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
01290    AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
01291    AST_APP_OPTION('H', OPT_CALLER_HANGUP),
01292    AST_APP_OPTION('i', OPT_IGNORE_CALL_FW),
01293    AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
01294    AST_APP_OPTION('k', OPT_CALLEE_PARK),
01295    AST_APP_OPTION('K', OPT_CALLER_PARK),
01296    AST_APP_OPTION('n', OPT_NO_RETRY),
01297    AST_APP_OPTION('r', OPT_RINGING),
01298    AST_APP_OPTION('R', OPT_RING_WHEN_RINGING),
01299    AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
01300    AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
01301    AST_APP_OPTION('x', OPT_CALLEE_AUTOMIXMON),
01302    AST_APP_OPTION('X', OPT_CALLER_AUTOMIXMON),
01303    AST_APP_OPTION('w', OPT_CALLEE_AUTOMON),
01304    AST_APP_OPTION('W', OPT_CALLER_AUTOMON),
01305 END_OPTIONS);
01306 
01307 enum {
01308    QUEUE_STRATEGY_RINGALL = 0,
01309    QUEUE_STRATEGY_LEASTRECENT,
01310    QUEUE_STRATEGY_FEWESTCALLS,
01311    QUEUE_STRATEGY_RANDOM,
01312    QUEUE_STRATEGY_RRMEMORY,
01313    QUEUE_STRATEGY_LINEAR,
01314    QUEUE_STRATEGY_WRANDOM,
01315    QUEUE_STRATEGY_RRORDERED,
01316 };
01317 
01318 enum {
01319      QUEUE_AUTOPAUSE_OFF = 0,
01320      QUEUE_AUTOPAUSE_ON,
01321      QUEUE_AUTOPAUSE_ALL
01322 };
01323 
01324 enum queue_reload_mask {
01325    QUEUE_RELOAD_PARAMETERS = (1 << 0),
01326    QUEUE_RELOAD_MEMBER = (1 << 1),
01327    QUEUE_RELOAD_RULES = (1 << 2),
01328    QUEUE_RESET_STATS = (1 << 3),
01329 };
01330 
01331 static const struct strategy {
01332    int strategy;
01333    const char *name;
01334 } strategies[] = {
01335    { QUEUE_STRATEGY_RINGALL, "ringall" },
01336    { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
01337    { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
01338    { QUEUE_STRATEGY_RANDOM, "random" },
01339    { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
01340    { QUEUE_STRATEGY_RRMEMORY, "roundrobin" },
01341    { QUEUE_STRATEGY_LINEAR, "linear" },
01342    { QUEUE_STRATEGY_WRANDOM, "wrandom"},
01343    { QUEUE_STRATEGY_RRORDERED, "rrordered"},
01344 };
01345 
01346 static const struct autopause {
01347    int autopause;
01348    const char *name;
01349 } autopausesmodes [] = {
01350    { QUEUE_AUTOPAUSE_OFF,"no" },
01351    { QUEUE_AUTOPAUSE_ON, "yes" },
01352    { QUEUE_AUTOPAUSE_ALL,"all" },
01353 };
01354 
01355 #define DEFAULT_RETRY      5
01356 #define DEFAULT_TIMEOUT    15
01357 #define RECHECK         1     /*!< Recheck every second to see we we're at the top yet */
01358 #define MAX_PERIODIC_ANNOUNCEMENTS 10           /*!< The maximum periodic announcements we can have */
01359 /*!
01360  * \brief The minimum number of seconds between position announcements.
01361  * \note The default value of 15 provides backwards compatibility.
01362  */
01363 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15
01364 
01365 #define MAX_QUEUE_BUCKETS 53
01366 
01367 #define  RES_OKAY 0     /*!< Action completed */
01368 #define  RES_EXISTS  (-1)     /*!< Entry already exists */
01369 #define  RES_OUTOFMEMORY   (-2)     /*!< Out of memory */
01370 #define  RES_NOSUCHQUEUE   (-3)     /*!< No such queue */
01371 #define RES_NOT_DYNAMIC (-4)     /*!< Member is not dynamic */
01372 
01373 static char *app = "Queue";
01374 
01375 static char *app_aqm = "AddQueueMember" ;
01376 
01377 static char *app_rqm = "RemoveQueueMember" ;
01378 
01379 static char *app_pqm = "PauseQueueMember" ;
01380 
01381 static char *app_upqm = "UnpauseQueueMember" ;
01382 
01383 static char *app_ql = "QueueLog" ;
01384 
01385 /*! \brief Persistent Members astdb family */
01386 static const char * const pm_family = "Queue/PersistentMembers";
01387 
01388 /*! \brief queues.conf [general] option */
01389 static int queue_persistent_members = 0;
01390 
01391 /*! \brief queues.conf per-queue weight option */
01392 static int use_weight = 0;
01393 
01394 /*! \brief queues.conf [general] option */
01395 static int autofill_default = 1;
01396 
01397 /*! \brief queues.conf [general] option */
01398 static int montype_default = 0;
01399 
01400 /*! \brief queues.conf [general] option */
01401 static int shared_lastcall = 1;
01402 
01403 /*! \brief queuesrules.conf [general] option */
01404 static int realtime_rules = 0;
01405 
01406 /*! \brief Subscription to device state change messages */
01407 static struct stasis_subscription *device_state_sub;
01408 
01409 /*! \brief queues.conf [general] option */
01410 static int update_cdr = 0;
01411 
01412 /*! \brief queues.conf [general] option */
01413 static int negative_penalty_invalid = 0;
01414 
01415 /*! \brief queues.conf [general] option */
01416 static int log_membername_as_agent = 0;
01417 
01418 /*! \brief name of the ringinuse field in the realtime database */
01419 static char *realtime_ringinuse_field;
01420 
01421 enum queue_result {
01422    QUEUE_UNKNOWN = 0,
01423    QUEUE_TIMEOUT = 1,
01424    QUEUE_JOINEMPTY = 2,
01425    QUEUE_LEAVEEMPTY = 3,
01426    QUEUE_JOINUNAVAIL = 4,
01427    QUEUE_LEAVEUNAVAIL = 5,
01428    QUEUE_FULL = 6,
01429    QUEUE_CONTINUE = 7,
01430 };
01431 
01432 static const struct {
01433    enum queue_result id;
01434    char *text;
01435 } queue_results[] = {
01436    { QUEUE_UNKNOWN, "UNKNOWN" },
01437    { QUEUE_TIMEOUT, "TIMEOUT" },
01438    { QUEUE_JOINEMPTY,"JOINEMPTY" },
01439    { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
01440    { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
01441    { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
01442    { QUEUE_FULL, "FULL" },
01443    { QUEUE_CONTINUE, "CONTINUE" },
01444 };
01445 
01446 enum queue_timeout_priority {
01447    TIMEOUT_PRIORITY_APP,
01448    TIMEOUT_PRIORITY_CONF,
01449 };
01450 
01451 /*! \brief We define a custom "local user" structure because we
01452  *  use it not only for keeping track of what is in use but
01453  *  also for keeping track of who we're dialing.
01454  *
01455  *  There are two "links" defined in this structure, q_next and call_next.
01456  *  q_next links ALL defined callattempt structures into a linked list. call_next is
01457  *  a link which allows for a subset of the callattempts to be traversed. This subset
01458  *  is used in wait_for_answer so that irrelevant callattempts are not traversed. This
01459  *  also is helpful so that queue logs are always accurate in the case where a call to
01460  *  a member times out, especially if using the ringall strategy.
01461 */
01462 
01463 struct callattempt {
01464    struct callattempt *q_next;
01465    struct callattempt *call_next;
01466    struct ast_channel *chan;
01467    char interface[256];       /*!< An Asterisk dial string (not a channel name) */
01468    int metric;
01469    time_t lastcall;
01470    struct call_queue *lastqueue;
01471    struct member *member;
01472    /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
01473    struct ast_party_connected_line connected;
01474    /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
01475    unsigned int pending_connected_update:1;
01476    /*! TRUE if the connected line update is blocked. */
01477    unsigned int block_connected_update:1;
01478    /*! TRUE if caller id is not available for connected line */
01479    unsigned int dial_callerid_absent:1;
01480    /*! TRUE if the call is still active */
01481    unsigned int stillgoing:1;
01482    struct ast_aoc_decoded *aoc_s_rate_list;
01483 };
01484 
01485 
01486 struct queue_ent {
01487    struct call_queue *parent;             /*!< What queue is our parent */
01488    char moh[MAX_MUSICCLASS];              /*!< Name of musiconhold to be used */
01489    char announce[PATH_MAX];               /*!< Announcement to play for member when call is answered */
01490    char context[AST_MAX_CONTEXT];         /*!< Context when user exits queue */
01491    char digits[AST_MAX_EXTENSION];        /*!< Digits entered while in queue */
01492    int valid_digits;                      /*!< Digits entered correspond to valid extension. Exited */
01493    int pos;                               /*!< Where we are in the queue */
01494    int prio;                              /*!< Our priority */
01495    int last_pos_said;                     /*!< Last position we told the user */
01496    int ring_when_ringing;                 /*!< Should we only use ring indication when a channel is ringing? */
01497    time_t last_periodic_announce_time;    /*!< The last time we played a periodic announcement */
01498    int last_periodic_announce_sound;      /*!< The last periodic announcement we made */
01499    time_t last_pos;                       /*!< Last time we told the user their position */
01500    int opos;                              /*!< Where we started in the queue */
01501    int handled;                           /*!< Whether our call was handled */
01502    int pending;                           /*!< Non-zero if we are attempting to call a member */
01503    int max_penalty;                       /*!< Limit the members that can take this call to this penalty or lower */
01504    int min_penalty;                       /*!< Limit the members that can take this call to this penalty or higher */
01505    int linpos;                            /*!< If using linear strategy, what position are we at? */
01506    int linwrapped;                        /*!< Is the linpos wrapped? */
01507    time_t start;                          /*!< When we started holding */
01508    time_t expire;                         /*!< When this entry should expire (time out of queue) */
01509    int cancel_answered_elsewhere;          /*!< Whether we should force the CAE flag on this call (C) option*/
01510    struct ast_channel *chan;              /*!< Our channel */
01511    AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
01512    struct penalty_rule *pr;               /*!< Pointer to the next penalty rule to implement */
01513    struct queue_ent *next;                /*!< The next queue entry */
01514 };
01515 
01516 struct member {
01517    char interface[AST_CHANNEL_NAME];    /*!< Technology/Location to dial to reach this member*/
01518    char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
01519    char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
01520    char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */
01521    char membername[80];                 /*!< Member name to use in queue logs */
01522    int penalty;                         /*!< Are we a last resort? */
01523    int calls;                           /*!< Number of calls serviced by this member */
01524    int dynamic;                         /*!< Are we dynamically added? */
01525    int realtime;                        /*!< Is this member realtime? */
01526    int status;                          /*!< Status of queue member */
01527    int paused;                          /*!< Are we paused (not accepting calls)? */
01528    int queuepos;                        /*!< In what order (pertains to certain strategies) should this member be called? */
01529    time_t lastcall;                     /*!< When last successful call was hungup */
01530    struct call_queue *lastqueue;      /*!< Last queue we received a call */
01531    unsigned int dead:1;                 /*!< Used to detect members deleted in realtime */
01532    unsigned int delme:1;                /*!< Flag to delete entry on reload */
01533    unsigned int call_pending:1;         /*!< TRUE if the Q is attempting to place a call to the member. */
01534    char rt_uniqueid[80];                /*!< Unique id of realtime member entry */
01535    unsigned int ringinuse:1;            /*!< Flag to ring queue members even if their status is 'inuse' */
01536 };
01537 
01538 enum empty_conditions {
01539    QUEUE_EMPTY_PENALTY = (1 << 0),
01540    QUEUE_EMPTY_PAUSED = (1 << 1),
01541    QUEUE_EMPTY_INUSE = (1 << 2),
01542    QUEUE_EMPTY_RINGING = (1 << 3),
01543    QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
01544    QUEUE_EMPTY_INVALID = (1 << 5),
01545    QUEUE_EMPTY_UNKNOWN = (1 << 6),
01546    QUEUE_EMPTY_WRAPUP = (1 << 7),
01547 };
01548 
01549 enum member_properties {
01550    MEMBER_PENALTY = 0,
01551    MEMBER_RINGINUSE = 1,
01552 };
01553 
01554 /* values used in multi-bit flags in call_queue */
01555 #define ANNOUNCEHOLDTIME_ALWAYS 1
01556 #define ANNOUNCEHOLDTIME_ONCE 2
01557 #define QUEUE_EVENT_VARIABLES 3
01558 
01559 struct penalty_rule {
01560    int time;                           /*!< Number of seconds that need to pass before applying this rule */
01561    int max_value;                      /*!< The amount specified in the penalty rule for max penalty */
01562    int min_value;                      /*!< The amount specified in the penalty rule for min penalty */
01563    int max_relative;                   /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
01564    int min_relative;                   /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
01565    AST_LIST_ENTRY(penalty_rule) list;  /*!< Next penalty_rule */
01566 };
01567 
01568 #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */
01569 #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */
01570 #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
01571 #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than <limit> */
01572 
01573 struct call_queue {
01574    AST_DECLARE_STRING_FIELDS(
01575       /*! Queue name */
01576       AST_STRING_FIELD(name);
01577       /*! Music on Hold class */
01578       AST_STRING_FIELD(moh);
01579       /*! Announcement to play when call is answered */
01580       AST_STRING_FIELD(announce);
01581       /*! Exit context */
01582       AST_STRING_FIELD(context);
01583       /*! Macro to run upon member connection */
01584       AST_STRING_FIELD(membermacro);
01585       /*! Gosub to run upon member connection */
01586       AST_STRING_FIELD(membergosub);
01587       /*! Default rule to use if none specified in call to Queue() */
01588       AST_STRING_FIELD(defaultrule);
01589       /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
01590       AST_STRING_FIELD(sound_next);
01591       /*! Sound file: "There are currently" (def. queue-thereare) */
01592       AST_STRING_FIELD(sound_thereare);
01593       /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
01594       AST_STRING_FIELD(sound_calls);
01595       /*! Sound file: "Currently there are more than" (def. queue-quantity1) */
01596       AST_STRING_FIELD(queue_quantity1);
01597       /*! Sound file: "callers waiting to speak with a representative" (def. queue-quantity2) */
01598       AST_STRING_FIELD(queue_quantity2);
01599       /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
01600       AST_STRING_FIELD(sound_holdtime);
01601       /*! Sound file: "minutes." (def. queue-minutes) */
01602       AST_STRING_FIELD(sound_minutes);
01603       /*! Sound file: "minute." (def. queue-minute) */
01604       AST_STRING_FIELD(sound_minute);
01605       /*! Sound file: "seconds." (def. queue-seconds) */
01606       AST_STRING_FIELD(sound_seconds);
01607       /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
01608       AST_STRING_FIELD(sound_thanks);
01609       /*! Sound file: Custom announce for caller, no default */
01610       AST_STRING_FIELD(sound_callerannounce);
01611       /*! Sound file: "Hold time" (def. queue-reporthold) */
01612       AST_STRING_FIELD(sound_reporthold);
01613    );
01614    /*! Sound files: Custom announce, no default */
01615    struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
01616    unsigned int dead:1;
01617    unsigned int ringinuse:1;
01618    unsigned int announce_to_first_user:1; /*!< Whether or not we announce to the first user in a queue */
01619    unsigned int setinterfacevar:1;
01620    unsigned int setqueuevar:1;
01621    unsigned int setqueueentryvar:1;
01622    unsigned int reportholdtime:1;
01623    unsigned int wrapped:1;
01624    unsigned int timeoutrestart:1;
01625    unsigned int announceholdtime:2;
01626    unsigned int announceposition:3;
01627    int strategy:4;
01628    unsigned int realtime:1;
01629    unsigned int found:1;
01630    unsigned int relativeperiodicannounce:1;
01631    unsigned int autopausebusy:1;
01632    unsigned int autopauseunavail:1;
01633    enum empty_conditions joinempty;
01634    enum empty_conditions leavewhenempty;
01635    int announcepositionlimit;          /*!< How many positions we announce? */
01636    int announcefrequency;              /*!< How often to announce their position */
01637    int minannouncefrequency;           /*!< The minimum number of seconds between position announcements (def. 15) */
01638    int periodicannouncefrequency;      /*!< How often to play periodic announcement */
01639    int numperiodicannounce;            /*!< The number of periodic announcements configured */
01640    int randomperiodicannounce;         /*!< Are periodic announcments randomly chosen */
01641    int roundingseconds;                /*!< How many seconds do we round to? */
01642    int holdtime;                       /*!< Current avg holdtime, based on an exponential average */
01643    int talktime;                       /*!< Current avg talktime, based on the same exponential average */
01644    int callscompleted;                 /*!< Number of queue calls completed */
01645    int callsabandoned;                 /*!< Number of queue calls abandoned */
01646    int servicelevel;                   /*!< seconds setting for servicelevel*/
01647    int callscompletedinsl;             /*!< Number of calls answered with servicelevel*/
01648    char monfmt[8];                     /*!< Format to use when recording calls */
01649    int montype;                        /*!< Monitor type  Monitor vs. MixMonitor */
01650    int count;                          /*!< How many entries */
01651    int maxlen;                         /*!< Max number of entries */
01652    int wrapuptime;                     /*!< Wrapup Time */
01653    int penaltymemberslimit;            /*!< Disregard penalty when queue has fewer than this many members */
01654 
01655    int retry;                          /*!< Retry calling everyone after this amount of time */
01656    int timeout;                        /*!< How long to wait for an answer */
01657    int weight;                         /*!< Respective weight */
01658    int autopause;                      /*!< Auto pause queue members if they fail to answer */
01659    int autopausedelay;                 /*!< Delay auto pause for autopausedelay seconds since last call */
01660    int timeoutpriority;                /*!< Do we allow a fraction of the timeout to occur for a ring? */
01661 
01662    /* Queue strategy things */
01663    int rrpos;                          /*!< Round Robin - position */
01664    int memberdelay;                    /*!< Seconds to delay connecting member to caller */
01665    int autofill;                       /*!< Ignore the head call status and ring an available agent */
01666 
01667    struct ao2_container *members;             /*!< Head of the list of members */
01668    struct queue_ent *head;             /*!< Head of the list of callers */
01669    AST_LIST_ENTRY(call_queue) list;    /*!< Next call queue */
01670    AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
01671 };
01672 
01673 struct rule_list {
01674    char name[80];
01675    AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
01676    AST_LIST_ENTRY(rule_list) list;
01677 };
01678 
01679 static AST_LIST_HEAD_STATIC(rule_lists, rule_list);
01680 
01681 static struct ao2_container *queues;
01682 
01683 static void update_realtime_members(struct call_queue *q);
01684 static struct member *interface_exists(struct call_queue *q, const char *interface);
01685 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
01686 
01687 static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface);
01688 /*! \brief sets the QUEUESTATUS channel variable */
01689 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
01690 {
01691    int i;
01692 
01693    for (i = 0; i < ARRAY_LEN(queue_results); i++) {
01694       if (queue_results[i].id == res) {
01695          pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
01696          return;
01697       }
01698    }
01699 }
01700 
01701 static const char *int2strat(int strategy)
01702 {
01703    int x;
01704 
01705    for (x = 0; x < ARRAY_LEN(strategies); x++) {
01706       if (strategy == strategies[x].strategy) {
01707          return strategies[x].name;
01708       }
01709    }
01710 
01711    return "<unknown>";
01712 }
01713 
01714 static int strat2int(const char *strategy)
01715 {
01716    int x;
01717 
01718    for (x = 0; x < ARRAY_LEN(strategies); x++) {
01719       if (!strcasecmp(strategy, strategies[x].name)) {
01720          return strategies[x].strategy;
01721       }
01722    }
01723 
01724    return -1;
01725 }
01726 
01727 static int autopause2int(const char *autopause)
01728 {
01729    int x;
01730    /*This 'double check' that default value is OFF */
01731    if (ast_strlen_zero(autopause)) {
01732       return QUEUE_AUTOPAUSE_OFF;
01733    }
01734 
01735    /*This 'double check' is to ensure old values works */
01736    if(ast_true(autopause)) {
01737       return QUEUE_AUTOPAUSE_ON;
01738    }
01739 
01740    for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
01741       if (!strcasecmp(autopause, autopausesmodes[x].name)) {
01742          return autopausesmodes[x].autopause;
01743       }
01744    }
01745 
01746    /*This 'double check' that default value is OFF */
01747    return QUEUE_AUTOPAUSE_OFF;
01748 }
01749 
01750 static int queue_hash_cb(const void *obj, const int flags)
01751 {
01752    const struct call_queue *q = obj;
01753 
01754    return ast_str_case_hash(q->name);
01755 }
01756 
01757 static int queue_cmp_cb(void *obj, void *arg, int flags)
01758 {
01759    struct call_queue *q = obj, *q2 = arg;
01760    return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
01761 }
01762 
01763 /*! \internal
01764  * \brief ao2_callback, Decreases queuepos of all followers with a queuepos greater than arg.
01765  * \param obj the member being acted on
01766  * \param arg pointer to an integer containing the position value that was removed and requires reduction for anything above
01767  */
01768 static int queue_member_decrement_followers(void *obj, void *arg, int flag)
01769 {
01770    struct member *mem = obj;
01771    int *decrement_followers_after = arg;
01772 
01773    if (mem->queuepos > *decrement_followers_after) {
01774       mem->queuepos--;
01775    }
01776 
01777    return 0;
01778 }
01779 
01780 /*! \internal
01781  * \brief ao2_callback, finds members in a queue marked for deletion and in a cascading fashion runs queue_member_decrement_followers
01782  *        on them. This callback should always be ran before performing mass unlinking of delmarked members from queues.
01783  * \param obj member being acted on
01784  * \param arg pointer to the queue members are being removed from
01785  */
01786 static int queue_delme_members_decrement_followers(void *obj, void *arg, int flag)
01787 {
01788    struct member *mem = obj;
01789    struct call_queue *queue = arg;
01790    int rrpos = mem->queuepos;
01791 
01792    if (mem->delme) {
01793       ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &rrpos);
01794    }
01795 
01796    return 0;
01797 }
01798 
01799 /*! \internal
01800  * \brief Use this to decrement followers during removal of a member
01801  * \param queue which queue the member is being removed from
01802  * \param mem which member is being removed from the queue
01803  */
01804 static void queue_member_follower_removal(struct call_queue *queue, struct member *mem)
01805 {
01806    int pos = mem->queuepos;
01807 
01808    /* If the position being removed is less than the current place in the queue, reduce the queue position by one so that we don't skip the member
01809     * who would have been next otherwise. */
01810    if (pos < queue->rrpos) {
01811       queue->rrpos--;
01812    }
01813 
01814    ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &pos);
01815 }
01816 
01817 #ifdef REF_DEBUG
01818 #define queue_ref(q)          _queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
01819 #define queue_unref(q)           _queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
01820 #define queue_t_ref(q, tag)         _queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01821 #define queue_t_unref(q, tag)    _queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01822 #define queues_t_link(c, q, tag) __ao2_link_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01823 #define queues_t_unlink(c, q, tag)  __ao2_unlink_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01824 
01825 static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
01826 {
01827    __ao2_ref_debug(q, 1, tag, file, line, filename);
01828    return q;
01829 }
01830 
01831 static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
01832 {
01833    if (q) {
01834       __ao2_ref_debug(q, -1, tag, file, line, filename);
01835    }
01836    return NULL;
01837 }
01838 
01839 #else
01840 
01841 #define queue_t_ref(q, tag)         queue_ref(q)
01842 #define queue_t_unref(q, tag)    queue_unref(q)
01843 #define queues_t_link(c, q, tag) ao2_t_link(c, q, tag)
01844 #define queues_t_unlink(c, q, tag)  ao2_t_unlink(c, q, tag)
01845 
01846 static inline struct call_queue *queue_ref(struct call_queue *q)
01847 {
01848    ao2_ref(q, 1);
01849    return q;
01850 }
01851 
01852 static inline struct call_queue *queue_unref(struct call_queue *q)
01853 {
01854    if (q) {
01855       ao2_ref(q, -1);
01856    }
01857    return NULL;
01858 }
01859 #endif
01860 
01861 /*! \brief Set variables of queue */
01862 static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
01863 {
01864    char interfacevar[256]="";
01865    float sl = 0;
01866 
01867    ao2_lock(q);
01868 
01869    if (q->setqueuevar) {
01870       sl = 0;
01871       if (q->callscompleted > 0) {
01872          sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
01873       }
01874 
01875       snprintf(interfacevar, sizeof(interfacevar),
01876          "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
01877          q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned,  q->servicelevel, sl);
01878 
01879       ao2_unlock(q);
01880 
01881       pbx_builtin_setvar_multiple(chan, interfacevar);
01882    } else {
01883       ao2_unlock(q);
01884    }
01885 }
01886 
01887 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
01888 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
01889 {
01890    struct queue_ent *cur;
01891 
01892    if (!q || !new)
01893       return;
01894    if (prev) {
01895       cur = prev->next;
01896       prev->next = new;
01897    } else {
01898       cur = q->head;
01899       q->head = new;
01900    }
01901    new->next = cur;
01902 
01903    /* every queue_ent must have a reference to it's parent call_queue, this
01904     * reference does not go away until the end of the queue_ent's life, meaning
01905     * that even when the queue_ent leaves the call_queue this ref must remain. */
01906    queue_ref(q);
01907    new->parent = q;
01908    new->pos = ++(*pos);
01909    new->opos = *pos;
01910 }
01911 
01912 static struct ast_manager_event_blob *queue_channel_to_ami(const char *type, struct stasis_message *message)
01913 {
01914    struct ast_channel_blob *obj = stasis_message_data(message);
01915    RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
01916    RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
01917 
01918    channel_string = ast_manager_build_channel_state_string(obj->snapshot);
01919    event_string = ast_manager_str_from_json_object(obj->blob, NULL);
01920    if (!channel_string || !event_string) {
01921       return NULL;
01922    }
01923 
01924    return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
01925       "%s"
01926       "%s",
01927       ast_str_buffer(channel_string),
01928       ast_str_buffer(event_string));
01929 }
01930 
01931 static struct ast_manager_event_blob *queue_caller_join_to_ami(struct stasis_message *message)
01932 {
01933    return queue_channel_to_ami("QueueCallerJoin", message);
01934 }
01935 
01936 static struct ast_manager_event_blob *queue_caller_leave_to_ami(struct stasis_message *message)
01937 {
01938    return queue_channel_to_ami("QueueCallerLeave", message);
01939 }
01940 
01941 static struct ast_manager_event_blob *queue_caller_abandon_to_ami(struct stasis_message *message)
01942 {
01943    return queue_channel_to_ami("QueueCallerAbandon", message);
01944 }
01945 
01946 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_join_type,
01947    .to_ami = queue_caller_join_to_ami,
01948    );
01949 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_leave_type,
01950    .to_ami = queue_caller_leave_to_ami,
01951    );
01952 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_caller_abandon_type,
01953    .to_ami = queue_caller_abandon_to_ami,
01954    );
01955 
01956 static struct ast_manager_event_blob *queue_member_to_ami(const char *type, struct stasis_message *message)
01957 {
01958    struct ast_json_payload *payload = stasis_message_data(message);
01959    RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
01960 
01961    event_string = ast_manager_str_from_json_object(payload->json, NULL);
01962    if (!event_string) {
01963       return NULL;
01964    }
01965 
01966    return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
01967       "%s",
01968       ast_str_buffer(event_string));
01969 }
01970 
01971 static struct ast_manager_event_blob *queue_member_status_to_ami(struct stasis_message *message)
01972 {
01973    return queue_member_to_ami("QueueMemberStatus", message);
01974 }
01975 
01976 static struct ast_manager_event_blob *queue_member_added_to_ami(struct stasis_message *message)
01977 {
01978    return queue_member_to_ami("QueueMemberAdded", message);
01979 }
01980 
01981 static struct ast_manager_event_blob *queue_member_removed_to_ami(struct stasis_message *message)
01982 {
01983    return queue_member_to_ami("QueueMemberRemoved", message);
01984 }
01985 
01986 static struct ast_manager_event_blob *queue_member_pause_to_ami(struct stasis_message *message)
01987 {
01988    return queue_member_to_ami("QueueMemberPause", message);
01989 }
01990 
01991 static struct ast_manager_event_blob *queue_member_penalty_to_ami(struct stasis_message *message)
01992 {
01993    return queue_member_to_ami("QueueMemberPenalty", message);
01994 }
01995 
01996 static struct ast_manager_event_blob *queue_member_ringinuse_to_ami(struct stasis_message *message)
01997 {
01998    return queue_member_to_ami("QueueMemberRinginuse", message);
01999 }
02000 
02001 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_status_type,
02002    .to_ami = queue_member_status_to_ami,
02003    );
02004 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_added_type,
02005    .to_ami = queue_member_added_to_ami,
02006    );
02007 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_removed_type,
02008    .to_ami = queue_member_removed_to_ami,
02009    );
02010 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_pause_type,
02011    .to_ami = queue_member_pause_to_ami,
02012    );
02013 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_penalty_type,
02014    .to_ami = queue_member_penalty_to_ami,
02015    );
02016 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_member_ringinuse_type,
02017    .to_ami = queue_member_ringinuse_to_ami,
02018    );
02019 
02020 static struct ast_manager_event_blob *queue_multi_channel_to_ami(const char *type, struct stasis_message *message)
02021 {
02022    struct ast_multi_channel_blob *obj = stasis_message_data(message);
02023    struct ast_channel_snapshot *caller;
02024    struct ast_channel_snapshot *agent;
02025    RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free);
02026    RAII_VAR(struct ast_str *, agent_event_string, NULL, ast_free);
02027    RAII_VAR(struct ast_str *, event_string, NULL, ast_free);
02028 
02029    caller = ast_multi_channel_blob_get_channel(obj, "caller");
02030    if (caller) {
02031       caller_event_string = ast_manager_build_channel_state_string(caller);
02032       if (!caller_event_string) {
02033          ast_log(LOG_NOTICE, "No caller event string, bailing\n");
02034          return NULL;
02035       }
02036    }
02037 
02038    agent = ast_multi_channel_blob_get_channel(obj, "agent");
02039    if (agent) {
02040       agent_event_string = ast_manager_build_channel_state_string_prefix(agent, "Dest");
02041       if (!agent_event_string) {
02042          ast_log(LOG_NOTICE, "No agent event string, bailing\n");
02043          return NULL;
02044       }
02045    }
02046 
02047    event_string = ast_manager_str_from_json_object(ast_multi_channel_blob_get_json(obj), NULL);
02048    if (!event_string) {
02049       return NULL;
02050    }
02051 
02052    return ast_manager_event_blob_create(EVENT_FLAG_AGENT, type,
02053       "%s"
02054       "%s"
02055       "%s",
02056       caller_event_string ? ast_str_buffer(caller_event_string) : "",
02057       agent_event_string ? ast_str_buffer(agent_event_string) : "",
02058       ast_str_buffer(event_string));
02059 }
02060 
02061 static struct ast_manager_event_blob *queue_agent_called_to_ami(struct stasis_message *message)
02062 {
02063    return queue_multi_channel_to_ami("AgentCalled", message);
02064 }
02065 
02066 static struct ast_manager_event_blob *queue_agent_connect_to_ami(struct stasis_message *message)
02067 {
02068    return queue_multi_channel_to_ami("AgentConnect", message);
02069 }
02070 
02071 static struct ast_manager_event_blob *queue_agent_complete_to_ami(struct stasis_message *message)
02072 {
02073    return queue_multi_channel_to_ami("AgentComplete", message);
02074 }
02075 
02076 static struct ast_manager_event_blob *queue_agent_dump_to_ami(struct stasis_message *message)
02077 {
02078    return queue_multi_channel_to_ami("AgentDump", message);
02079 }
02080 
02081 static struct ast_manager_event_blob *queue_agent_ringnoanswer_to_ami(struct stasis_message *message)
02082 {
02083    return queue_multi_channel_to_ami("AgentRingNoAnswer", message);
02084 }
02085 
02086 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_called_type,
02087    .to_ami = queue_agent_called_to_ami,
02088    );
02089 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_connect_type,
02090    .to_ami = queue_agent_connect_to_ami,
02091    );
02092 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_complete_type,
02093    .to_ami = queue_agent_complete_to_ami,
02094    );
02095 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_dump_type,
02096    .to_ami = queue_agent_dump_to_ami,
02097    );
02098 STASIS_MESSAGE_TYPE_DEFN_LOCAL(queue_agent_ringnoanswer_type,
02099    .to_ami = queue_agent_ringnoanswer_to_ami,
02100    );
02101 
02102 static void queue_publish_multi_channel_snapshot_blob(struct stasis_topic *topic,
02103       struct ast_channel_snapshot *caller_snapshot,
02104       struct ast_channel_snapshot *agent_snapshot,
02105       struct stasis_message_type *type, struct ast_json *blob)
02106 {
02107    RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
02108    RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
02109 
02110    if (!type) {
02111       return;
02112    }
02113 
02114    payload = ast_multi_channel_blob_create(blob);
02115    if (!payload) {
02116       return;
02117    }
02118 
02119    ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
02120    if (agent_snapshot) {
02121       ast_multi_channel_blob_add_channel(payload, "agent", agent_snapshot);
02122    }
02123 
02124    msg = stasis_message_create(type, payload);
02125    if (!msg) {
02126       return;
02127    }
02128 
02129    stasis_publish(topic, msg);
02130 }
02131 
02132 static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct ast_channel *agent,
02133       struct stasis_message_type *type, struct ast_json *blob)
02134 {
02135    RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
02136    RAII_VAR(struct ast_channel_snapshot *, agent_snapshot, NULL, ao2_cleanup);
02137 
02138    ast_channel_lock(caller);
02139    caller_snapshot = ast_channel_snapshot_create(caller);
02140    ast_channel_unlock(caller);
02141    ast_channel_lock(agent);
02142    agent_snapshot = ast_channel_snapshot_create(agent);
02143    ast_channel_unlock(agent);
02144 
02145    if (!caller_snapshot || !agent_snapshot) {
02146       return;
02147    }
02148 
02149    queue_publish_multi_channel_snapshot_blob(ast_channel_topic(caller), caller_snapshot,
02150          agent_snapshot, type, blob);
02151 }
02152 
02153 /*!
02154  * \internal
02155  * \brief Publish the member blob.
02156  * \since 12.0.0
02157  *
02158  * \param type Stasis message type to publish.
02159  * \param blob The information being published.
02160  *
02161  * \note The json blob reference is passed to this function.
02162  *
02163  * \return Nothing
02164  */
02165 static void queue_publish_member_blob(struct stasis_message_type *type, struct ast_json *blob)
02166 {
02167    RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
02168    RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
02169 
02170    if (!blob || !type) {
02171       return;
02172    }
02173 
02174    payload = ast_json_payload_create(blob);
02175    ast_json_unref(blob);
02176    if (!payload) {
02177       return;
02178    }
02179 
02180    msg = stasis_message_create(type, payload);
02181    if (!msg) {
02182       return;
02183    }
02184 
02185    stasis_publish(ast_manager_get_topic(), msg);
02186 }
02187 
02188 static struct ast_json *queue_member_blob_create(struct call_queue *q, struct member *mem)
02189 {
02190    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}",
02191       "Queue", q->name,
02192       "MemberName", mem->membername,
02193       "Interface", mem->interface,
02194       "StateInterface", mem->state_interface,
02195       "Membership", (mem->dynamic ? "dynamic" : (mem->realtime ? "realtime" : "static")),
02196       "Penalty", mem->penalty,
02197       "CallsTaken", mem->calls,
02198       "LastCall", (int)mem->lastcall,
02199       "Status", mem->status,
02200       "Paused", mem->paused,
02201       "Ringinuse", mem->ringinuse);
02202 }
02203 
02204 /*! \brief Check if members are available
02205  *
02206  * This function checks to see if members are available to be called. If any member
02207  * is available, the function immediately returns 0. If no members are available,
02208  * then -1 is returned.
02209  */
02210 static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions, int devstate)
02211 {
02212    struct member *member;
02213    struct ao2_iterator mem_iter;
02214 
02215    ao2_lock(q);
02216    mem_iter = ao2_iterator_init(q->members, 0);
02217    for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
02218       if ((max_penalty != INT_MAX && member->penalty > max_penalty) || (min_penalty != INT_MAX && member->penalty < min_penalty)) {
02219          if (conditions & QUEUE_EMPTY_PENALTY) {
02220             ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
02221             continue;
02222          }
02223       }
02224 
02225       switch (devstate ? ast_device_state(member->state_interface) : member->status) {
02226       case AST_DEVICE_INVALID:
02227          if (conditions & QUEUE_EMPTY_INVALID) {
02228             ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
02229             break;
02230          }
02231          goto default_case;
02232       case AST_DEVICE_UNAVAILABLE:
02233          if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
02234             ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
02235             break;
02236          }
02237          goto default_case;
02238       case AST_DEVICE_INUSE:
02239          if (conditions & QUEUE_EMPTY_INUSE) {
02240             ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
02241             break;
02242          }
02243          goto default_case;
02244       case AST_DEVICE_RINGING:
02245          if (conditions & QUEUE_EMPTY_RINGING) {
02246             ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
02247             break;
02248          }
02249          goto default_case;
02250       case AST_DEVICE_UNKNOWN:
02251          if (conditions & QUEUE_EMPTY_UNKNOWN) {
02252             ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
02253             break;
02254          }
02255          /* Fall-through */
02256       default:
02257       default_case:
02258          if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
02259             ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
02260             break;
02261          } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
02262             ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
02263             break;
02264          } else {
02265             ao2_ref(member, -1);
02266             ao2_iterator_destroy(&mem_iter);
02267             ao2_unlock(q);
02268             ast_debug(4, "%s is available.\n", member->membername);
02269             return 0;
02270          }
02271          break;
02272       }
02273    }
02274    ao2_iterator_destroy(&mem_iter);
02275    ao2_unlock(q);
02276 
02277    if (!devstate && (conditions & QUEUE_EMPTY_RINGING)) {
02278       /* member state still may be RINGING due to lag in event message - check again with device state */
02279       return get_member_status(q, max_penalty, min_penalty, conditions, 1);
02280    }
02281    return -1;
02282 }
02283 
02284 /*! \brief set a member's status based on device state of that member's state_interface.
02285  *
02286  * Lock interface list find sc, iterate through each queues queue_member list for member to
02287  * update state inside queues
02288 */
02289 static void update_status(struct call_queue *q, struct member *m, const int status)
02290 {
02291    m->status = status;
02292 
02293    queue_publish_member_blob(queue_member_status_type(), queue_member_blob_create(q, m));
02294 }
02295 
02296 /*!
02297  * \internal
02298  * \brief Determine if a queue member is available
02299  * \retval 1 if the member is available
02300  * \retval 0 if the member is not available
02301  */
02302 static int is_member_available(struct call_queue *q, struct member *mem)
02303 {
02304    int available = 0;
02305 
02306    switch (mem->status) {
02307       case AST_DEVICE_INVALID:
02308       case AST_DEVICE_UNAVAILABLE:
02309          break;
02310       case AST_DEVICE_INUSE:
02311       case AST_DEVICE_BUSY:
02312       case AST_DEVICE_RINGING:
02313       case AST_DEVICE_RINGINUSE:
02314       case AST_DEVICE_ONHOLD:
02315          if (!mem->ringinuse) {
02316             break;
02317          }
02318          /* else fall through */
02319       case AST_DEVICE_NOT_INUSE:
02320       case AST_DEVICE_UNKNOWN:
02321          if (!mem->paused) {
02322             available = 1;
02323          }
02324          break;
02325    }
02326 
02327    /* Let wrapuptimes override device state availability */
02328    if (mem->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < mem->lastcall)) {
02329       available = 0;
02330    }
02331    return available;
02332 }
02333 
02334 /*! \brief set a member's status based on device state of that member's interface*/
02335 static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
02336 {
02337    struct ao2_iterator miter, qiter;
02338    struct ast_device_state_message *dev_state;
02339    struct member *m;
02340    struct call_queue *q;
02341    char interface[80], *slash_pos;
02342    int found = 0;       /* Found this member in any queue */
02343    int found_member;    /* Found this member in this queue */
02344    int avail = 0;       /* Found an available member in this queue */
02345 
02346    if (ast_device_state_message_type() != stasis_message_type(msg)) {
02347       return;
02348    }
02349 
02350    dev_state = stasis_message_data(msg);
02351    if (dev_state->eid) {
02352       /* ignore non-aggregate states */
02353       return;
02354    }
02355 
02356    qiter = ao2_iterator_init(queues, 0);
02357    while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
02358       ao2_lock(q);
02359 
02360       avail = 0;
02361       found_member = 0;
02362       miter = ao2_iterator_init(q->members, 0);
02363       for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
02364          if (!found_member) {
02365             ast_copy_string(interface, m->state_interface, sizeof(interface));
02366 
02367             if ((slash_pos = strchr(interface, '/'))) {
02368                if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
02369                   *slash_pos = '\0';
02370                }
02371             }
02372 
02373             if (!strcasecmp(interface, dev_state->device)) {
02374                found_member = 1;
02375                update_status(q, m, dev_state->state);
02376             }
02377          }
02378 
02379          /* check every member until we find one NOT_INUSE */
02380          if (!avail) {
02381             avail = is_member_available(q, m);
02382          }
02383          if (avail && found_member) {
02384             /* early exit as we've found an available member and the member of interest */
02385             ao2_ref(m, -1);
02386             break;
02387          }
02388       }
02389 
02390       if (found_member) {
02391          found = 1;
02392          if (avail) {
02393             ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
02394          } else {
02395             ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
02396          }
02397       }
02398 
02399       ao2_iterator_destroy(&miter);
02400 
02401       ao2_unlock(q);
02402       queue_t_unref(q, "Done with iterator");
02403    }
02404    ao2_iterator_destroy(&qiter);
02405 
02406    if (found) {
02407       ast_debug(1, "Device '%s' changed to state '%u' (%s)\n",
02408          dev_state->device,
02409          dev_state->state,
02410          ast_devstate2str(dev_state->state));
02411    } else {
02412       ast_debug(3, "Device '%s' changed to state '%u' (%s) but we don't care because they're not a member of any queue.\n",
02413          dev_state->device,
02414          dev_state->state,
02415          ast_devstate2str(dev_state->state));
02416    }
02417 
02418    return;
02419 }
02420 
02421 /*! \brief Helper function which converts from extension state to device state values */
02422 static int extensionstate2devicestate(int state)
02423 {
02424    switch (state) {
02425    case AST_EXTENSION_NOT_INUSE:
02426       state = AST_DEVICE_NOT_INUSE;
02427       break;
02428    case AST_EXTENSION_INUSE:
02429       state = AST_DEVICE_INUSE;
02430       break;
02431    case AST_EXTENSION_BUSY:
02432       state = AST_DEVICE_BUSY;
02433       break;
02434    case AST_EXTENSION_RINGING:
02435       state = AST_DEVICE_RINGING;
02436       break;
02437    case AST_EXTENSION_ONHOLD:
02438       state = AST_DEVICE_ONHOLD;
02439       break;
02440    case AST_EXTENSION_UNAVAILABLE:
02441       state = AST_DEVICE_UNAVAILABLE;
02442       break;
02443    case AST_EXTENSION_REMOVED:
02444    case AST_EXTENSION_DEACTIVATED:
02445    default:
02446       state = AST_DEVICE_INVALID;
02447       break;
02448    }
02449 
02450    return state;
02451 }
02452 
02453 static int extension_state_cb(char *context, char *exten, struct ast_state_cb_info *info, void *data)
02454 {
02455    struct ao2_iterator miter, qiter;
02456    struct member *m;
02457    struct call_queue *q;
02458    int state = info->exten_state;
02459    int found = 0, device_state = extensionstate2devicestate(state);
02460 
02461    /* only interested in extension state updates involving device states */
02462    if (info->reason != AST_HINT_UPDATE_DEVICE) {
02463       return 0;
02464    }
02465 
02466    qiter = ao2_iterator_init(queues, 0);
02467    while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
02468       ao2_lock(q);
02469 
02470       miter = ao2_iterator_init(q->members, 0);
02471       for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
02472          if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
02473             update_status(q, m, device_state);
02474             ao2_ref(m, -1);
02475             found = 1;
02476             break;
02477          }
02478       }
02479       ao2_iterator_destroy(&miter);
02480 
02481       ao2_unlock(q);
02482       queue_t_unref(q, "Done with iterator");
02483    }
02484    ao2_iterator_destroy(&qiter);
02485 
02486         if (found) {
02487       ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
02488    } else {
02489       ast_debug(3, "Extension '%s@%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
02490            exten, context, device_state, ast_devstate2str(device_state));
02491    }
02492 
02493    return 0;
02494 }
02495 
02496 /*! \brief Return the current state of a member */
02497 static int get_queue_member_status(struct member *cur)
02498 {
02499    return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
02500 }
02501 
02502 /*! \brief allocate space for new queue member and set fields based on parameters passed */
02503 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
02504 {
02505    struct member *cur;
02506 
02507    if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
02508       cur->ringinuse = ringinuse;
02509       cur->penalty = penalty;
02510       cur->paused = paused;
02511       ast_copy_string(cur->interface, interface, sizeof(cur->interface));
02512       if (!ast_strlen_zero(state_interface)) {
02513          ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
02514       } else {
02515          ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
02516       }
02517       if (!ast_strlen_zero(membername)) {
02518          ast_copy_string(cur->membername, membername, sizeof(cur->membername));
02519       } else {
02520          ast_copy_string(cur->membername, interface, sizeof(cur->membername));
02521       }
02522       if (!strchr(cur->interface, '/')) {
02523          ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
02524       }
02525       if (!strncmp(cur->state_interface, "hint:", 5)) {
02526          char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
02527          char *exten = strsep(&context, "@") + 5;
02528 
02529          ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
02530          ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
02531       }
02532       cur->status = get_queue_member_status(cur);
02533    }
02534 
02535    return cur;
02536 }
02537 
02538 
02539 static int compress_char(const char c)
02540 {
02541    if (c < 32) {
02542       return 0;
02543    } else if (c > 96) {
02544       return c - 64;
02545    }
02546    return c - 32;
02547 }
02548 
02549 static int member_hash_fn(const void *obj, const int flags)
02550 {
02551    const struct member *mem = obj;
02552    const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
02553    const char *chname = strchr(interface, '/');
02554    int ret = 0, i;
02555 
02556    if (!chname) {
02557       chname = interface;
02558    }
02559    for (i = 0; i < 5 && chname[i]; i++) {
02560       ret += compress_char(chname[i]) << (i * 6);
02561    }
02562    return ret;
02563 }
02564 
02565 static int member_cmp_fn(void *obj1, void *obj2, int flags)
02566 {
02567    struct member *mem1 = obj1;
02568    struct member *mem2 = obj2;
02569    const char *interface = (flags & OBJ_KEY) ? obj2 : mem2->interface;
02570 
02571    return strcasecmp(mem1->interface, interface) ? 0 : CMP_MATCH | CMP_STOP;
02572 }
02573 
02574 /*!
02575  * \brief Initialize Queue default values.
02576  * \note the queue's lock  must be held before executing this function
02577 */
02578 static void init_queue(struct call_queue *q)
02579 {
02580    int i;
02581    struct penalty_rule *pr_iter;
02582 
02583    q->dead = 0;
02584    q->retry = DEFAULT_RETRY;
02585    q->timeout = DEFAULT_TIMEOUT;
02586    q->maxlen = 0;
02587    q->announcefrequency = 0;
02588    q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
02589    q->announceholdtime = 1;
02590    q->announcepositionlimit = 10; /* Default 10 positions */
02591    q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
02592    q->roundingseconds = 0; /* Default - don't announce seconds */
02593    q->servicelevel = 0;
02594    q->ringinuse = 1;
02595    q->announce_to_first_user = 0;
02596    q->setinterfacevar = 0;
02597    q->setqueuevar = 0;
02598    q->setqueueentryvar = 0;
02599    q->autofill = autofill_default;
02600    q->montype = montype_default;
02601    q->monfmt[0] = '\0';
02602    q->reportholdtime = 0;
02603    q->wrapuptime = 0;
02604    q->penaltymemberslimit = 0;
02605    q->joinempty = 0;
02606    q->leavewhenempty = 0;
02607    q->memberdelay = 0;
02608    q->weight = 0;
02609    q->timeoutrestart = 0;
02610    q->periodicannouncefrequency = 0;
02611    q->randomperiodicannounce = 0;
02612    q->numperiodicannounce = 0;
02613    q->autopause = QUEUE_AUTOPAUSE_OFF;
02614    q->timeoutpriority = TIMEOUT_PRIORITY_APP;
02615    q->autopausedelay = 0;
02616    if (!q->members) {
02617       if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED) {
02618          /* linear strategy depends on order, so we have to place all members in a single bucket */
02619          q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
02620       } else {
02621          q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
02622       }
02623    }
02624    q->found = 1;
02625 
02626    ast_string_field_set(q, sound_next, "queue-youarenext");
02627    ast_string_field_set(q, sound_thereare, "queue-thereare");
02628    ast_string_field_set(q, sound_calls, "queue-callswaiting");
02629    ast_string_field_set(q, queue_quantity1, "queue-quantity1");
02630    ast_string_field_set(q, queue_quantity2, "queue-quantity2");
02631    ast_string_field_set(q, sound_holdtime, "queue-holdtime");
02632    ast_string_field_set(q, sound_minutes, "queue-minutes");
02633    ast_string_field_set(q, sound_minute, "queue-minute");
02634    ast_string_field_set(q, sound_seconds, "queue-seconds");
02635    ast_string_field_set(q, sound_thanks, "queue-thankyou");
02636    ast_string_field_set(q, sound_reporthold, "queue-reporthold");
02637 
02638    if (!q->sound_periodicannounce[0]) {
02639       q->sound_periodicannounce[0] = ast_str_create(32);
02640    }
02641 
02642    if (q->sound_periodicannounce[0]) {
02643       ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
02644    }
02645 
02646    for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
02647       if (q->sound_periodicannounce[i]) {
02648          ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
02649       }
02650    }
02651 
02652    while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list))) {
02653       ast_free(pr_iter);
02654    }
02655 
02656    /* On restart assume no members are available.
02657     * The queue_avail hint is a boolean state to indicate whether a member is available or not.
02658     *
02659     * This seems counter intuitive, but is required to light a BLF
02660     * AST_DEVICE_INUSE indicates no members are available.
02661     * AST_DEVICE_NOT_INUSE indicates a member is available.
02662     */
02663    ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
02664 }
02665 
02666 static void clear_queue(struct call_queue *q)
02667 {
02668    q->holdtime = 0;
02669    q->callscompleted = 0;
02670    q->callsabandoned = 0;
02671    q->callscompletedinsl = 0;
02672    q->talktime = 0;
02673 
02674    if (q->members) {
02675       struct member *mem;
02676       struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
02677       while ((mem = ao2_iterator_next(&mem_iter))) {
02678          mem->calls = 0;
02679          mem->lastcall = 0;
02680          ao2_ref(mem, -1);
02681       }
02682       ao2_iterator_destroy(&mem_iter);
02683    }
02684 }
02685 
02686 /*!
02687  * \brief Change queue penalty by adding rule.
02688  *
02689  * Check rule for errors with time or fomatting, see if rule is relative to rest
02690  * of queue, iterate list of rules to find correct insertion point, insert and return.
02691  * \retval -1 on failure
02692  * \retval 0 on success
02693  * \note Call this with the rule_lists locked
02694 */
02695 static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
02696 {
02697    char *timestr, *maxstr, *minstr, *contentdup;
02698    struct penalty_rule *rule = NULL, *rule_iter;
02699    struct rule_list *rl_iter;
02700    int penaltychangetime, inserted = 0;
02701 
02702    if (!(rule = ast_calloc(1, sizeof(*rule)))) {
02703       return -1;
02704    }
02705 
02706    contentdup = ast_strdupa(content);
02707 
02708    if (!(maxstr = strchr(contentdup, ','))) {
02709       ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
02710       ast_free(rule);
02711       return -1;
02712    }
02713 
02714    *maxstr++ = '\0';
02715    timestr = contentdup;
02716 
02717    if ((penaltychangetime = atoi(timestr)) < 0) {
02718       ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
02719       ast_free(rule);
02720       return -1;
02721    }
02722 
02723    rule->time = penaltychangetime;
02724 
02725    if ((minstr = strchr(maxstr,','))) {
02726       *minstr++ = '\0';
02727    }
02728 
02729    /* The last check will evaluate true if either no penalty change is indicated for a given rule
02730     * OR if a min penalty change is indicated but no max penalty change is */
02731    if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
02732       rule->max_relative = 1;
02733    }
02734 
02735    rule->max_value = atoi(maxstr);
02736 
02737    if (!ast_strlen_zero(minstr)) {
02738       if (*minstr == '+' || *minstr == '-') {
02739          rule->min_relative = 1;
02740       }
02741       rule->min_value = atoi(minstr);
02742    } else { /*there was no minimum specified, so assume this means no change*/
02743       rule->min_relative = 1;
02744    }
02745 
02746    /*We have the rule made, now we need to insert it where it belongs*/
02747    AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
02748       if (strcasecmp(rl_iter->name, list_name)) {
02749          continue;
02750       }
02751 
02752       AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
02753          if (rule->time < rule_iter->time) {
02754             AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
02755             inserted = 1;
02756             break;
02757          }
02758       }
02759       AST_LIST_TRAVERSE_SAFE_END;
02760 
02761       if (!inserted) {
02762          AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
02763          inserted = 1;
02764       }
02765 
02766       break;
02767    }
02768 
02769    if (!inserted) {
02770       ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name);
02771       ast_free(rule);
02772       return -1;
02773    }
02774    return 0;
02775 }
02776 
02777 /*!
02778  * \brief Load queue rules from realtime.
02779  *
02780  * Check rule for errors with time or fomatting, see if rule is relative to rest
02781  * of queue, iterate list of rules to find correct insertion point, insert and return.
02782  * \retval -1 on failure
02783  * \retval 0 on success
02784  * \note Call this with the rule_lists locked
02785 */
02786 static int load_realtime_rules(void)
02787 {
02788    struct ast_config *cfg;
02789         struct rule_list *rl_iter, *new_rl;
02790         struct penalty_rule *pr_iter;
02791         char *rulecat = NULL;
02792 
02793    if (!ast_check_realtime("queue_rules")) {
02794       ast_log(LOG_WARNING, "Missing \"queue_rules\" in extconfig.conf\n");
02795       return 0;
02796    }
02797    if (!(cfg = ast_load_realtime_multientry("queue_rules", "rule_name LIKE", "%", SENTINEL))) {
02798       ast_log(LOG_WARNING, "Failed to load queue rules from realtime\n");
02799       return 0;
02800    }
02801    while ((rulecat = ast_category_browse(cfg, rulecat)) && !ast_strlen_zero(rulecat)) {
02802       const char *timestr, *maxstr, *minstr;
02803       int penaltychangetime, rule_exists = 0, inserted = 0;
02804       int max_penalty = 0, min_penalty = 0, min_relative = 0, max_relative = 0;
02805       struct penalty_rule *new_penalty_rule = NULL;
02806       AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
02807          if (!(strcasecmp(rl_iter->name, rulecat))) {
02808             rule_exists = 1;
02809             new_rl = rl_iter;
02810             break;
02811          }
02812       }
02813       if (!rule_exists) {
02814          if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
02815             ast_config_destroy(cfg);
02816             return -1;
02817          }
02818          ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name));
02819          AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list);
02820       }
02821       timestr = ast_variable_retrieve(cfg, rulecat, "time");
02822       if (!(timestr) || sscanf(timestr, "%30d", &penaltychangetime) != 1) {
02823          ast_log(LOG_NOTICE, "Failed to parse time (%s) for one of the %s rules, skipping it\n",
02824             (ast_strlen_zero(timestr) ? "invalid value" : timestr), rulecat);
02825          continue;
02826       }
02827       if (!(new_penalty_rule = ast_calloc(1, sizeof(*new_penalty_rule)))) {
02828          ast_config_destroy(cfg);
02829          return -1;
02830       }
02831       if (!(maxstr = ast_variable_retrieve(cfg, rulecat, "max_penalty")) ||
02832          ast_strlen_zero(maxstr) || sscanf(maxstr, "%30d", &max_penalty) != 1) {
02833          max_penalty = 0;
02834          max_relative = 1;
02835       } else {
02836          if (*maxstr == '+' || *maxstr == '-') {
02837             max_relative = 1;
02838          }
02839       }
02840       if (!(minstr = ast_variable_retrieve(cfg, rulecat, "min_penalty")) ||
02841          ast_strlen_zero(minstr) || sscanf(minstr, "%30d", &min_penalty) != 1) {
02842          min_penalty = 0;
02843          min_relative = 1;
02844       } else {
02845          if (*minstr == '+' || *minstr == '-') {
02846             min_relative = 1;
02847          }
02848       }
02849       new_penalty_rule->time = penaltychangetime;
02850       new_penalty_rule->max_relative = max_relative;
02851       new_penalty_rule->max_value = max_penalty;
02852       new_penalty_rule->min_relative = min_relative;
02853       new_penalty_rule->min_value = min_penalty;
02854       AST_LIST_TRAVERSE_SAFE_BEGIN(&new_rl->rules, pr_iter, list) {
02855          if (new_penalty_rule->time < pr_iter->time) {
02856             AST_LIST_INSERT_BEFORE_CURRENT(new_penalty_rule, list);
02857             inserted = 1;
02858          }
02859       }
02860       AST_LIST_TRAVERSE_SAFE_END;
02861       if (!inserted) {
02862          AST_LIST_INSERT_TAIL(&new_rl->rules, new_penalty_rule, list);
02863       }
02864    }
02865 
02866    ast_config_destroy(cfg);
02867    return 0;
02868 }
02869 
02870 static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
02871 {
02872    char *value_copy = ast_strdupa(value);
02873    char *option = NULL;
02874    while ((option = strsep(&value_copy, ","))) {
02875       if (!strcasecmp(option, "paused")) {
02876          *empty |= QUEUE_EMPTY_PAUSED;
02877       } else if (!strcasecmp(option, "penalty")) {
02878          *empty |= QUEUE_EMPTY_PENALTY;
02879       } else if (!strcasecmp(option, "inuse")) {
02880          *empty |= QUEUE_EMPTY_INUSE;
02881       } else if (!strcasecmp(option, "ringing")) {
02882          *empty |= QUEUE_EMPTY_RINGING;
02883       } else if (!strcasecmp(option, "invalid")) {
02884          *empty |= QUEUE_EMPTY_INVALID;
02885       } else if (!strcasecmp(option, "wrapup")) {
02886          *empty |= QUEUE_EMPTY_WRAPUP;
02887       } else if (!strcasecmp(option, "unavailable")) {
02888          *empty |= QUEUE_EMPTY_UNAVAILABLE;
02889       } else if (!strcasecmp(option, "unknown")) {
02890          *empty |= QUEUE_EMPTY_UNKNOWN;
02891       } else if (!strcasecmp(option, "loose")) {
02892          *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID);
02893       } else if (!strcasecmp(option, "strict")) {
02894          *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED | QUEUE_EMPTY_UNAVAILABLE);
02895       } else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
02896          *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED);
02897       } else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
02898          *empty = 0;
02899       } else {
02900          ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
02901       }
02902    }
02903 }
02904 
02905 /*! \brief Configure a queue parameter.
02906  *
02907  * The failunknown flag is set for config files (and static realtime) to show
02908  * errors for unknown parameters. It is cleared for dynamic realtime to allow
02909  *  extra fields in the tables.
02910  * \note For error reporting, line number is passed for .conf static configuration,
02911  * for Realtime queues, linenum is -1.
02912 */
02913 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
02914 {
02915    if (!strcasecmp(param, "musicclass") ||
02916       !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
02917       ast_string_field_set(q, moh, val);
02918    } else if (!strcasecmp(param, "announce")) {
02919       ast_string_field_set(q, announce, val);
02920    } else if (!strcasecmp(param, "context")) {
02921       ast_string_field_set(q, context, val);
02922    } else if (!strcasecmp(param, "timeout")) {
02923       q->timeout = atoi(val);
02924       if (q->timeout < 0) {
02925          q->timeout = DEFAULT_TIMEOUT;
02926       }
02927    } else if (!strcasecmp(param, "ringinuse")) {
02928       q->ringinuse = ast_true(val);
02929    } else if (!strcasecmp(param, "setinterfacevar")) {
02930       q->setinterfacevar = ast_true(val);
02931    } else if (!strcasecmp(param, "setqueuevar")) {
02932       q->setqueuevar = ast_true(val);
02933    } else if (!strcasecmp(param, "setqueueentryvar")) {
02934       q->setqueueentryvar = ast_true(val);
02935    } else if (!strcasecmp(param, "monitor-format")) {
02936       ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
02937    } else if (!strcasecmp(param, "membermacro")) {
02938       ast_string_field_set(q, membermacro, val);
02939    } else if (!strcasecmp(param, "membergosub")) {
02940       ast_string_field_set(q, membergosub, val);
02941    } else if (!strcasecmp(param, "queue-youarenext")) {
02942       ast_string_field_set(q, sound_next, val);
02943    } else if (!strcasecmp(param, "queue-thereare")) {
02944       ast_string_field_set(q, sound_thereare, val);
02945    } else if (!strcasecmp(param, "queue-callswaiting")) {
02946       ast_string_field_set(q, sound_calls, val);
02947    } else if (!strcasecmp(param, "queue-quantity1")) {
02948       ast_string_field_set(q, queue_quantity1, val);
02949    } else if (!strcasecmp(param, "queue-quantity2")) {
02950       ast_string_field_set(q, queue_quantity2, val);
02951    } else if (!strcasecmp(param, "queue-holdtime")) {
02952       ast_string_field_set(q, sound_holdtime, val);
02953    } else if (!strcasecmp(param, "queue-minutes")) {
02954       ast_string_field_set(q, sound_minutes, val);
02955    } else if (!strcasecmp(param, "queue-minute")) {
02956       ast_string_field_set(q, sound_minute, val);
02957    } else if (!strcasecmp(param, "queue-seconds")) {
02958       ast_string_field_set(q, sound_seconds, val);
02959    } else if (!strcasecmp(param, "queue-thankyou")) {
02960       ast_string_field_set(q, sound_thanks, val);
02961    } else if (!strcasecmp(param, "queue-callerannounce")) {
02962       ast_string_field_set(q, sound_callerannounce, val);
02963    } else if (!strcasecmp(param, "queue-reporthold")) {
02964       ast_string_field_set(q, sound_reporthold, val);
02965    } else if (!strcasecmp(param, "announce-frequency")) {
02966       q->announcefrequency = atoi(val);
02967    } else if (!strcasecmp(param, "announce-to-first-user")) {
02968       q->announce_to_first_user = ast_true(val);
02969    } else if (!strcasecmp(param, "min-announce-frequency")) {
02970       q->minannouncefrequency = atoi(val);
02971       ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
02972    } else if (!strcasecmp(param, "announce-round-seconds")) {
02973       q->roundingseconds = atoi(val);
02974       /* Rounding to any other values just doesn't make sense... */
02975       if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
02976          || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
02977          if (linenum >= 0) {
02978             ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
02979                "using 0 instead for queue '%s' at line %d of queues.conf\n",
02980                val, param, q->name, linenum);
02981          } else {
02982             ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
02983                "using 0 instead for queue '%s'\n", val, param, q->name);
02984          }
02985          q->roundingseconds=0;
02986       }
02987    } else if (!strcasecmp(param, "announce-holdtime")) {
02988       if (!strcasecmp(val, "once")) {
02989          q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
02990       } else if (ast_true(val)) {
02991          q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
02992       } else {
02993          q->announceholdtime = 0;
02994       }
02995    } else if (!strcasecmp(param, "announce-position")) {
02996       if (!strcasecmp(val, "limit")) {
02997          q->announceposition = ANNOUNCEPOSITION_LIMIT;
02998       } else if (!strcasecmp(val, "more")) {
02999          q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
03000       } else if (ast_true(val)) {
03001          q->announceposition = ANNOUNCEPOSITION_YES;
03002       } else {
03003          q->announceposition = ANNOUNCEPOSITION_NO;
03004       }
03005    } else if (!strcasecmp(param, "announce-position-limit")) {
03006       q->announcepositionlimit = atoi(val);
03007    } else if (!strcasecmp(param, "periodic-announce")) {
03008       if (strchr(val, ',')) {
03009          char *s, *buf = ast_strdupa(val);
03010          unsigned int i = 0;
03011 
03012          while ((s = strsep(&buf, ",|"))) {
03013             if (!q->sound_periodicannounce[i]) {
03014                q->sound_periodicannounce[i] = ast_str_create(16);
03015             }
03016             ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
03017             i++;
03018             if (i == MAX_PERIODIC_ANNOUNCEMENTS) {
03019                break;
03020             }
03021          }
03022          q->numperiodicannounce = i;
03023       } else {
03024          ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
03025          q->numperiodicannounce = 1;
03026       }
03027    } else if (!strcasecmp(param, "periodic-announce-frequency")) {
03028       q->periodicannouncefrequency = atoi(val);
03029    } else if (!strcasecmp(param, "relative-periodic-announce")) {
03030       q->relativeperiodicannounce = ast_true(val);
03031    } else if (!strcasecmp(param, "random-periodic-announce")) {
03032       q->randomperiodicannounce = ast_true(val);
03033    } else if (!strcasecmp(param, "retry")) {
03034       q->retry = atoi(val);
03035       if (q->retry <= 0) {
03036          q->retry = DEFAULT_RETRY;
03037       }
03038    } else if (!strcasecmp(param, "wrapuptime")) {
03039       q->wrapuptime = atoi(val);
03040    } else if (!strcasecmp(param, "penaltymemberslimit")) {
03041       if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
03042          q->penaltymemberslimit = 0;
03043       }
03044    } else if (!strcasecmp(param, "autofill")) {
03045       q->autofill = ast_true(val);
03046    } else if (!strcasecmp(param, "monitor-type")) {
03047       if (!strcasecmp(val, "mixmonitor")) {
03048          q->montype = 1;
03049       }
03050    } else if (!strcasecmp(param, "autopause")) {
03051       q->autopause = autopause2int(val);
03052    } else if (!strcasecmp(param, "autopausedelay")) {
03053       q->autopausedelay = atoi(val);
03054    } else if (!strcasecmp(param, "autopausebusy")) {
03055       q->autopausebusy = ast_true(val);
03056    } else if (!strcasecmp(param, "autopauseunavail")) {
03057       q->autopauseunavail = ast_true(val);
03058    } else if (!strcasecmp(param, "maxlen")) {
03059       q->maxlen = atoi(val);
03060       if (q->maxlen < 0) {
03061          q->maxlen = 0;
03062       }
03063    } else if (!strcasecmp(param, "servicelevel")) {
03064       q->servicelevel= atoi(val);
03065    } else if (!strcasecmp(param, "strategy")) {
03066       int strategy;
03067 
03068       /* We are a static queue and already have set this, no need to do it again */
03069       if (failunknown) {
03070          return;
03071       }
03072       strategy = strat2int(val);
03073       if (strategy < 0) {
03074          ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
03075             val, q->name);
03076          q->strategy = QUEUE_STRATEGY_RINGALL;
03077       }
03078       if (strategy == q->strategy) {
03079          return;
03080       }
03081       if (strategy == QUEUE_STRATEGY_LINEAR) {
03082          ast_log(LOG_WARNING, "Changing to the linear strategy currently requires asterisk to be restarted.\n");
03083          return;
03084       }
03085       q->strategy = strategy;
03086    } else if (!strcasecmp(param, "joinempty")) {
03087       parse_empty_options(val, &q->joinempty, 1);
03088    } else if (!strcasecmp(param, "leavewhenempty")) {
03089       parse_empty_options(val, &q->leavewhenempty, 0);
03090    } else if (!strcasecmp(param, "reportholdtime")) {
03091       q->reportholdtime = ast_true(val);
03092    } else if (!strcasecmp(param, "memberdelay")) {
03093       q->memberdelay = atoi(val);
03094    } else if (!strcasecmp(param, "weight")) {
03095       q->weight = atoi(val);
03096    } else if (!strcasecmp(param, "timeoutrestart")) {
03097       q->timeoutrestart = ast_true(val);
03098    } else if (!strcasecmp(param, "defaultrule")) {
03099       ast_string_field_set(q, defaultrule, val);
03100    } else if (!strcasecmp(param, "timeoutpriority")) {
03101       if (!strcasecmp(val, "conf")) {
03102          q->timeoutpriority = TIMEOUT_PRIORITY_CONF;
03103       } else {
03104          q->timeoutpriority = TIMEOUT_PRIORITY_APP;
03105       }
03106    } else if (failunknown) {
03107       if (linenum >= 0) {
03108          ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
03109             q->name, param, linenum);
03110       } else {
03111          ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
03112       }
03113    }
03114 }
03115 
03116 
03117 #define QUEUE_PAUSED_DEVSTATE AST_DEVICE_INUSE
03118 #define QUEUE_UNPAUSED_DEVSTATE AST_DEVICE_NOT_INUSE
03119 #define QUEUE_UNKNOWN_PAUSED_DEVSTATE AST_DEVICE_NOT_INUSE
03120 
03121 /*! \internal
03122  * \brief If adding a single new member to a queue, use this function instead of ao2_linking.
03123  *        This adds round robin queue position data for a fresh member as well as links it.
03124  * \param queue Which queue the member is being added to
03125  * \param mem Which member is being added to the queue
03126  */
03127 static void member_add_to_queue(struct call_queue *queue, struct member *mem)
03128 {
03129    ao2_lock(queue->members);
03130    mem->queuepos = ao2_container_count(queue->members);
03131    ao2_link(queue->members, mem);
03132    ast_devstate_changed(mem->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE,
03133       AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", queue->name, mem->interface);
03134    ao2_unlock(queue->members);
03135 }
03136 
03137 /*! \internal
03138  * \brief If removing a single member from a queue, use this function instead of ao2_unlinking.
03139  *        This will perform round robin queue position reordering for the remaining members.
03140  * \param queue Which queue the member is being removed from
03141  * \param member Which member is being removed from the queue
03142  */
03143 static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
03144 {
03145    ao2_lock(queue->members);
03146    ast_devstate_changed(QUEUE_UNKNOWN_PAUSED_DEVSTATE, AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", queue->name, mem->interface);
03147    queue_member_follower_removal(queue, mem);
03148    ao2_unlink(queue->members, mem);
03149    ao2_unlock(queue->members);
03150 }
03151 
03152 /*!
03153  * \brief Find rt member record to update otherwise create one.
03154  *
03155  * Search for member in queue, if found update penalty/paused state,
03156  * if no member exists create one flag it as a RT member and add to queue member list.
03157 */
03158 static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config)
03159 {
03160    struct member *m;
03161    struct ao2_iterator mem_iter;
03162    int penalty = 0;
03163    int paused  = 0;
03164    int found = 0;
03165    int ringinuse = q->ringinuse;
03166 
03167    const char *config_val;
03168    const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
03169    const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface);
03170    const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface);
03171    const char *penalty_str = ast_variable_retrieve(member_config, interface, "penalty");
03172    const char *paused_str = ast_variable_retrieve(member_config, interface, "paused");
03173 
03174    if (ast_strlen_zero(rt_uniqueid)) {
03175       ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));
03176       return;
03177    }
03178 
03179    if (penalty_str) {
03180       penalty = atoi(penalty_str);
03181       if ((penalty < 0) && negative_penalty_invalid) {
03182          return;
03183       } else if (penalty < 0) {
03184          penalty = 0;
03185       }
03186    }
03187 
03188    if (paused_str) {
03189       paused = atoi(paused_str);
03190       if (paused < 0) {
03191          paused = 0;
03192       }
03193    }
03194 
03195    if ((config_val = ast_variable_retrieve(member_config, interface, realtime_ringinuse_field))) {
03196       if (ast_true(config_val)) {
03197          ringinuse = 1;
03198       } else if (ast_false(config_val)) {
03199          ringinuse = 0;
03200       } else {
03201          ast_log(LOG_WARNING, "Invalid value of '%s' field for %s in queue '%s'\n", realtime_ringinuse_field, interface, q->name);
03202       }
03203    }
03204 
03205    /* Find member by realtime uniqueid and update */
03206    mem_iter = ao2_iterator_init(q->members, 0);
03207    while ((m = ao2_iterator_next(&mem_iter))) {
03208       if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
03209          m->dead = 0;   /* Do not delete this one. */
03210          ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
03211          if (paused_str) {
03212             m->paused = paused;
03213             ast_devstate_changed(m->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE,
03214                AST_DEVSTATE_CACHABLE, "Queue:%s_pause_%s", q->name, m->interface);
03215          }
03216          if (strcasecmp(state_interface, m->state_interface)) {
03217             ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
03218          }
03219          m->penalty = penalty;
03220          m->ringinuse = ringinuse;
03221          found = 1;
03222          ao2_ref(m, -1);
03223          break;
03224       }
03225       ao2_ref(m, -1);
03226    }
03227    ao2_iterator_destroy(&mem_iter);
03228 
03229    /* Create a new member */
03230    if (!found) {
03231       if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse))) {
03232          m->dead = 0;
03233          m->realtime = 1;
03234          ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
03235          if (!log_membername_as_agent) {
03236             ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
03237          } else {
03238             ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
03239          }
03240          member_add_to_queue(q, m);
03241          ao2_ref(m, -1);
03242          m = NULL;
03243       }
03244    }
03245 }
03246 
03247 /*! \brief Iterate through queue's member list and delete them */
03248 static void free_members(struct call_queue *q, int all)
03249 {
03250    /* Free non-dynamic members */
03251    struct member *cur;
03252    struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
03253 
03254    while ((cur = ao2_iterator_next(&mem_iter))) {
03255       if (all || !cur->dynamic) {
03256          member_remove_from_queue(q, cur);
03257       }
03258       ao2_ref(cur, -1);
03259    }
03260    ao2_iterator_destroy(&mem_iter);
03261 }
03262 
03263 /*! \brief Free queue's member list then its string fields */
03264 static void destroy_queue(void *obj)
03265 {
03266    struct call_queue *q = obj;
03267    int i;
03268 
03269    free_members(q, 1);
03270    ast_string_field_free_memory(q);
03271    for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
03272       if (q->sound_periodicannounce[i]) {
03273          ast_free(q->sound_periodicannounce[i]);
03274       }
03275    }
03276    ao2_ref(q->members, -1);
03277 }
03278 
03279 static struct call_queue *alloc_queue(const char *queuename)
03280 {
03281    struct call_queue *q;
03282 
03283    if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
03284       if (ast_string_field_init(q, 64)) {
03285          queue_t_unref(q, "String field allocation failed");
03286          return NULL;
03287       }
03288       ast_string_field_set(q, name, queuename);
03289    }
03290    return q;
03291 }
03292 
03293 /*!
03294  * \brief Reload a single queue via realtime.
03295  *
03296  * Check for statically defined queue first, check if deleted RT queue,
03297  * check for new RT queue, if queue vars are not defined init them with defaults.
03298  * reload RT queue vars, set RT queue members dead and reload them, return finished queue.
03299  * \retval the queue,
03300  * \retval NULL if it doesn't exist.
03301  * \note Should be called with the "queues" container locked.
03302 */
03303 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
03304 {
03305    struct ast_variable *v;
03306    struct call_queue *q, tmpq = {
03307       .name = queuename,
03308    };
03309    struct member *m;
03310    struct ao2_iterator mem_iter;
03311    char *interface = NULL;
03312    const char *tmp_name;
03313    char *tmp;
03314    char tmpbuf[64];  /* Must be longer than the longest queue param name. */
03315 
03316    /* Static queues override realtime. */
03317    if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
03318       ao2_lock(q);
03319       if (!q->realtime) {
03320          if (q->dead) {
03321             ao2_unlock(q);
03322             queue_t_unref(q, "Queue is dead; can't return it");
03323             return NULL;
03324          }
03325          ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
03326          ao2_unlock(q);
03327          return q;
03328       }
03329    } else if (!member_config) {
03330       /* Not found in the list, and it's not realtime ... */
03331       return NULL;
03332    }
03333    /* Check if queue is defined in realtime. */
03334    if (!queue_vars) {
03335       /* Delete queue from in-core list if it has been deleted in realtime. */
03336       if (q) {
03337          /*! \note Hmm, can't seem to distinguish a DB failure from a not
03338             found condition... So we might delete an in-core queue
03339             in case of DB failure. */
03340          ast_debug(1, "Queue %s not found in realtime.\n", queuename);
03341 
03342          q->dead = 1;
03343          /* Delete if unused (else will be deleted when last caller leaves). */
03344          queues_t_unlink(queues, q, "Unused; removing from container");
03345          ao2_unlock(q);
03346          queue_t_unref(q, "Queue is dead; can't return it");
03347       }
03348       return NULL;
03349    }
03350 
03351    /* Create a new queue if an in-core entry does not exist yet. */
03352    if (!q) {
03353       struct ast_variable *tmpvar = NULL;
03354       if (!(q = alloc_queue(queuename))) {
03355          return NULL;
03356       }
03357       ao2_lock(q);
03358       clear_queue(q);
03359       q->realtime = 1;
03360       /*Before we initialize the queue, we need to set the strategy, so that linear strategy
03361        * will allocate the members properly
03362        */
03363       for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
03364          if (!strcasecmp(tmpvar->name, "strategy")) {
03365             q->strategy = strat2int(tmpvar->value);
03366             if (q->strategy < 0) {
03367                ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
03368                tmpvar->value, q->name);
03369                q->strategy = QUEUE_STRATEGY_RINGALL;
03370             }
03371             break;
03372          }
03373       }
03374       /* We traversed all variables and didn't find a strategy */
03375       if (!tmpvar) {
03376          q->strategy = QUEUE_STRATEGY_RINGALL;
03377       }
03378       queues_t_link(queues, q, "Add queue to container");
03379    }
03380    init_queue(q);    /* Ensure defaults for all parameters not set explicitly. */
03381 
03382    memset(tmpbuf, 0, sizeof(tmpbuf));
03383    for (v = queue_vars; v; v = v->next) {
03384       /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
03385       if (strchr(v->name, '_')) {
03386          ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
03387          tmp_name = tmpbuf;
03388          tmp = tmpbuf;
03389          while ((tmp = strchr(tmp, '_'))) {
03390             *tmp++ = '-';
03391          }
03392       } else {
03393          tmp_name = v->name;
03394       }
03395 
03396       /* NULL values don't get returned from realtime; blank values should
03397        * still get set.  If someone doesn't want a value to be set, they
03398        * should set the realtime column to NULL, not blank. */
03399       queue_set_param(q, tmp_name, v->value, -1, 0);
03400    }
03401 
03402    /* Temporarily set realtime members dead so we can detect deleted ones. */
03403    mem_iter = ao2_iterator_init(q->members, 0);
03404    while ((m = ao2_iterator_next(&mem_iter))) {
03405       if (m->realtime) {
03406          m->dead = 1;
03407       }
03408       ao2_ref(m, -1);
03409    }
03410    ao2_iterator_destroy(&mem_iter);
03411 
03412    while ((interface = ast_category_browse(member_config, interface))) {
03413       rt_handle_member_record(q, interface, member_config);
03414    }
03415 
03416    /* Delete all realtime members that have been deleted in DB. */
03417    mem_iter = ao2_iterator_init(q->members, 0);
03418    while ((m = ao2_iterator_next(&mem_iter))) {
03419       if (m->dead) {
03420          if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
03421             ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
03422          } else {
03423             ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
03424          }
03425          member_remove_from_queue(q, m);
03426       }
03427       ao2_ref(m, -1);
03428    }
03429    ao2_iterator_destroy(&mem_iter);
03430 
03431    ao2_unlock(q);
03432 
03433    return q;
03434 }
03435 
03436 /*!
03437  * note  */
03438 
03439 /*!
03440  * \internal
03441  * \brief Returns reference to the named queue. If the queue is realtime, it will load the queue as well.
03442  * \param queuename - name of the desired queue
03443  *
03444  * \retval the queue
03445  * \retval NULL if it doesn't exist
03446  */
03447 static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
03448 {
03449    struct ast_variable *queue_vars;
03450    struct ast_config *member_config = NULL;
03451    struct call_queue *q = NULL, tmpq = {
03452       .name = queuename,
03453    };
03454    int prev_weight = 0;
03455 
03456    /* Find the queue in the in-core list first. */
03457    q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
03458 
03459    if (!q || q->realtime) {
03460       /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
03461          queue operations while waiting for the DB.
03462 
03463          This will be two separate database transactions, so we might
03464          see queue parameters as they were before another process
03465          changed the queue and member list as it was after the change.
03466          Thus we might see an empty member list when a queue is
03467          deleted. In practise, this is unlikely to cause a problem. */
03468 
03469       queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
03470       if (queue_vars) {
03471          member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
03472          if (!member_config) {
03473             ast_debug(1, "No queue_members defined in config extconfig.conf\n");
03474             member_config = ast_config_new();
03475          }
03476       }
03477       if (q) {
03478          prev_weight = q->weight ? 1 : 0;
03479          queue_t_unref(q, "Need to find realtime queue");
03480       }
03481 
03482       q = find_queue_by_name_rt(queuename, queue_vars, member_config);
03483       ast_config_destroy(member_config);
03484       ast_variables_destroy(queue_vars);
03485 
03486       /* update the use_weight value if the queue's has gained or lost a weight */
03487       if (q) {
03488          if (!q->weight && prev_weight) {
03489             ast_atomic_fetchadd_int(&use_weight, -1);
03490          }
03491          if (q->weight && !prev_weight) {
03492             ast_atomic_fetchadd_int(&use_weight, +1);
03493          }
03494       }
03495       /* Other cases will end up with the proper value for use_weight */
03496    } else {
03497       update_realtime_members(q);
03498    }
03499    return q;
03500 }
03501 
03502 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
03503 {
03504    int ret = -1;
03505 
03506    if (ast_strlen_zero(mem->rt_uniqueid)) {
03507       return ret;
03508    }
03509 
03510    if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) > 0) {
03511       ret = 0;
03512    }
03513 
03514    return ret;
03515 }
03516 
03517 
03518 static void update_realtime_members(struct call_queue *q)
03519 {
03520    struct ast_config *member_config = NULL;
03521    struct member *m;
03522    char *interface = NULL;
03523    struct ao2_iterator mem_iter;
03524 
03525    if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
03526       /* This queue doesn't have realtime members. If the queue still has any realtime
03527        * members in memory, they need to be removed.
03528        */
03529       ao2_lock(q);
03530       mem_iter = ao2_iterator_init(q->members, 0);
03531       while ((m = ao2_iterator_next(&mem_iter))) {
03532          if (m->realtime) {
03533             member_remove_from_queue(q, m);
03534          }
03535          ao2_ref(m, -1);
03536       }
03537       ao2_iterator_destroy(&mem_iter);
03538       ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
03539       ao2_unlock(q);
03540       return;
03541    }
03542 
03543    ao2_lock(q);
03544 
03545    /* Temporarily set realtime  members dead so we can detect deleted ones.*/
03546    mem_iter = ao2_iterator_init(q->members, 0);
03547    while ((m = ao2_iterator_next(&mem_iter))) {
03548       if (m->realtime) {
03549          m->dead = 1;
03550       }
03551       ao2_ref(m, -1);
03552    }
03553    ao2_iterator_destroy(&mem_iter);
03554 
03555    while ((interface = ast_category_browse(member_config, interface))) {
03556       rt_handle_member_record(q, interface, member_config);
03557    }
03558 
03559    /* Delete all realtime members that have been deleted in DB. */
03560    mem_iter = ao2_iterator_init(q->members, 0);
03561    while ((m = ao2_iterator_next(&mem_iter))) {
03562       if (m->dead) {
03563          if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
03564             ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
03565          } else {
03566             ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
03567          }
03568          member_remove_from_queue(q, m);
03569       }
03570       ao2_ref(m, -1);
03571    }
03572    ao2_iterator_destroy(&mem_iter);
03573    ao2_unlock(q);
03574    ast_config_destroy(member_config);
03575 }
03576 
03577 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
03578 {
03579    struct call_queue *q;
03580    struct queue_ent *cur, *prev = NULL;
03581    int res = -1;
03582    int pos = 0;
03583    int inserted = 0;
03584 
03585    if (!(q = find_load_queue_rt_friendly(queuename))) {
03586       return res;
03587    }
03588    ao2_lock(q);
03589 
03590    /* This is our one */
03591    if (q->joinempty) {
03592       int status = 0;
03593       if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty, 0))) {
03594          *reason = QUEUE_JOINEMPTY;
03595          ao2_unlock(q);
03596          queue_t_unref(q, "Done with realtime queue");
03597          return res;
03598       }
03599    }
03600    if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen)) {
03601       *reason = QUEUE_FULL;
03602    } else if (*reason == QUEUE_UNKNOWN) {
03603       RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
03604 
03605       /* There's space for us, put us at the right position inside
03606        * the queue.
03607        * Take into account the priority of the calling user */
03608       inserted = 0;
03609       prev = NULL;
03610       cur = q->head;
03611       while (cur) {
03612          /* We have higher priority than the current user, enter
03613           * before him, after all the other users with priority
03614           * higher or equal to our priority. */
03615          if ((!inserted) && (qe->prio > cur->prio)) {
03616             insert_entry(q, prev, qe, &pos);
03617             inserted = 1;
03618          }
03619          /* <= is necessary for the position comparison because it may not be possible to enter
03620           * at our desired position since higher-priority callers may have taken the position we want
03621           */
03622          if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
03623             insert_entry(q, prev, qe, &pos);
03624             inserted = 1;
03625             /*pos is incremented inside insert_entry, so don't need to add 1 here*/
03626             if (position < pos) {
03627                ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
03628             }
03629          }
03630          cur->pos = ++pos;
03631          prev = cur;
03632          cur = cur->next;
03633       }
03634       /* No luck, join at the end of the queue */
03635       if (!inserted) {
03636          insert_entry(q, prev, qe, &pos);
03637       }
03638       ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
03639       ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
03640       ast_copy_string(qe->context, q->context, sizeof(qe->context));
03641       q->count++;
03642       if (q->count == 1) {
03643          ast_devstate_changed(AST_DEVICE_RINGING, AST_DEVSTATE_CACHABLE, "Queue:%s", q->name);
03644       }
03645 
03646       res = 0;
03647 
03648       blob = ast_json_pack("{s: s, s: i, s: i}",
03649                  "Queue", q->name,
03650                  "Position", qe->pos,
03651                  "Count", q->count);
03652       ast_channel_publish_cached_blob(qe->chan, queue_caller_join_type(), blob);
03653       ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
03654    }
03655    ao2_unlock(q);
03656    queue_t_unref(q, "Done with realtime queue");
03657 
03658    return res;
03659 }
03660 
03661 static int play_file(struct ast_channel *chan, const char *filename)
03662 {
03663    int res;
03664 
03665    if (ast_strlen_zero(filename)) {
03666       return 0;
03667    }
03668 
03669    if (!ast_fileexists(filename, NULL, ast_channel_language(chan))) {
03670       return 0;
03671    }
03672 
03673    ast_stopstream(chan);
03674 
03675    res = ast_streamfile(chan, filename, ast_channel_language(chan));
03676    if (!res) {
03677       res = ast_waitstream(chan, AST_DIGIT_ANY);
03678    }
03679 
03680    ast_stopstream(chan);
03681 
03682    return res;
03683 }
03684 
03685 /*!
03686  * \brief Check for valid exit from queue via goto
03687  * \retval 0 if failure
03688  * \retval 1 if successful
03689 */
03690 static int valid_exit(struct queue_ent *qe, char digit)
03691 {
03692    int digitlen = strlen(qe->digits);
03693 
03694    /* Prevent possible buffer overflow */
03695    if (digitlen < sizeof(qe->digits) - 2) {
03696       qe->digits[digitlen] = digit;
03697       qe->digits[digitlen + 1] = '\0';
03698    } else {
03699       qe->digits[0] = '\0';
03700       return 0;
03701    }
03702 
03703    /* If there's no context to goto, short-circuit */
03704    if (ast_strlen_zero(qe->context)) {
03705       return 0;
03706    }
03707 
03708    /* If the extension is bad, then reset the digits to blank */
03709    if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
03710       S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, NULL))) {
03711       qe->digits[0] = '\0';
03712       return 0;
03713    }
03714 
03715    /* We have an exact match */
03716    if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
03717       qe->valid_digits = 1;
03718       /* Return 1 on a successful goto */
03719       return 1;
03720    }
03721 
03722    return 0;
03723 }
03724 
03725 static int say_position(struct queue_ent *qe, int ringing)
03726 {
03727    int res = 0, announceposition = 0;
03728    long avgholdmins, avgholdsecs;
03729    int say_thanks = 1;
03730    time_t now;
03731 
03732    /* Let minannouncefrequency seconds pass between the start of each position announcement */
03733    time(&now);
03734    if ((now - qe->last_pos) < qe->parent->minannouncefrequency) {
03735       return 0;
03736    }
03737 
03738    /* If either our position has changed, or we are over the freq timer, say position */
03739    if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency)) {
03740       return 0;
03741    }
03742 
03743    if (ringing) {
03744       ast_indicate(qe->chan,-1);
03745    } else {
03746       ast_moh_stop(qe->chan);
03747    }
03748 
03749    if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
03750       qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
03751       (qe->parent->announceposition == ANNOUNCEPOSITION_LIMIT &&
03752       qe->pos <= qe->parent->announcepositionlimit)) {
03753          announceposition = 1;
03754    }
03755 
03756 
03757    if (announceposition == 1) {
03758       /* Say we're next, if we are */
03759       if (qe->pos == 1) {
03760          res = play_file(qe->chan, qe->parent->sound_next);
03761          if (res) {
03762             goto playout;
03763          }
03764          goto posout;
03765       } else {
03766          if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
03767             /* More than Case*/
03768             res = play_file(qe->chan, qe->parent->queue_quantity1);
03769             if (res) {
03770                goto playout;
03771             }
03772             res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */
03773             if (res) {
03774                goto playout;
03775             }
03776          } else {
03777             /* Normal Case */
03778             res = play_file(qe->chan, qe->parent->sound_thereare);
03779             if (res) {
03780                goto playout;
03781             }
03782             res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */
03783             if (res) {
03784                goto playout;
03785             }
03786          }
03787          if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
03788             /* More than Case*/
03789             res = play_file(qe->chan, qe->parent->queue_quantity2);
03790             if (res) {
03791                goto playout;
03792             }
03793          } else {
03794             res = play_file(qe->chan, qe->parent->sound_calls);
03795             if (res) {
03796                goto playout;
03797             }
03798          }
03799       }
03800    }
03801    /* Round hold time to nearest minute */
03802    avgholdmins = labs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
03803 
03804    /* If they have specified a rounding then round the seconds as well */
03805    if (qe->parent->roundingseconds) {
03806       avgholdsecs = (labs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
03807       avgholdsecs *= qe->parent->roundingseconds;
03808    } else {
03809       avgholdsecs = 0;
03810    }
03811 
03812    ast_verb(3, "Hold time for %s is %ld minute(s) %ld seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
03813 
03814    /* If the hold time is >1 min, if it's enabled, and if it's not
03815       supposed to be only once and we have already said it, say it */
03816    if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
03817       ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
03818       !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
03819       res = play_file(qe->chan, qe->parent->sound_holdtime);
03820       if (res) {
03821          goto playout;
03822       }
03823 
03824       if (avgholdmins >= 1) {
03825          res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
03826          if (res) {
03827             goto playout;
03828          }
03829 
03830          if (avgholdmins == 1) {
03831             res = play_file(qe->chan, qe->parent->sound_minute);
03832             if (res) {
03833                goto playout;
03834             }
03835          } else {
03836             res = play_file(qe->chan, qe->parent->sound_minutes);
03837             if (res) {
03838                goto playout;
03839             }
03840          }
03841       }
03842       if (avgholdsecs >= 1) {
03843          res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
03844          if (res) {
03845             goto playout;
03846          }
03847 
03848          res = play_file(qe->chan, qe->parent->sound_seconds);
03849          if (res) {
03850             goto playout;
03851          }
03852       }
03853    } else if (qe->parent->announceholdtime && !qe->parent->announceposition) {
03854       say_thanks = 0;
03855    }
03856 
03857 posout:
03858    if (qe->parent->announceposition) {
03859       ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
03860          ast_channel_name(qe->chan), qe->parent->name, qe->pos);
03861    }
03862    if (say_thanks) {
03863       res = play_file(qe->chan, qe->parent->sound_thanks);
03864    }
03865 playout:
03866 
03867    if ((res > 0 && !valid_exit(qe, res))) {
03868       res = 0;
03869    }
03870 
03871    /* Set our last_pos indicators */
03872    qe->last_pos = now;
03873    qe->last_pos_said = qe->pos;
03874 
03875    /* Don't restart music on hold if we're about to exit the caller from the queue */
03876    if (!res) {
03877       if (ringing) {
03878          ast_indicate(qe->chan, AST_CONTROL_RINGING);
03879       } else {
03880          ast_moh_start(qe->chan, qe->moh, NULL);
03881       }
03882    }
03883    return res;
03884 }
03885 
03886 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
03887 {
03888    int oldvalue;
03889 
03890    /* Calculate holdtime using an exponential average */
03891    /* Thanks to SRT for this contribution */
03892    /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
03893 
03894    ao2_lock(qe->parent);
03895    oldvalue = qe->parent->holdtime;
03896    qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
03897    ao2_unlock(qe->parent);
03898 }
03899 
03900 /*! \brief Caller leaving queue.
03901  *
03902  * Search the queue to find the leaving client, if found remove from queue
03903  * create manager event, move others up the queue.
03904 */
03905 static void leave_queue(struct queue_ent *qe)
03906 {
03907    struct call_queue *q;
03908    struct queue_ent *current, *prev = NULL;
03909    struct penalty_rule *pr_iter;
03910    int pos = 0;
03911 
03912    if (!(q = qe->parent)) {
03913       return;
03914    }
03915    queue_t_ref(q, "Copy queue pointer from queue entry");
03916    ao2_lock(q);
03917 
03918    prev = NULL;
03919    for (current = q->head; current; current = current->next) {
03920       if (current == qe) {
03921          RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
03922          char posstr[20];
03923          q->count--;
03924          if (!q->count) {
03925             ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s", q->name);
03926          }
03927 
03928          blob = ast_json_pack("{s: s, s: i, s: i}",
03929                     "Queue", q->name,
03930                     "Position", qe->pos,
03931                     "Count", q->count);
03932          ast_channel_publish_cached_blob(qe->chan, queue_caller_leave_type(), blob);
03933          ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
03934          /* Take us out of the queue */
03935          if (prev) {
03936             prev->next = current->next;
03937          } else {
03938             q->head = current->next;
03939          }
03940          /* Free penalty rules */
03941          while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list))) {
03942             ast_free(pr_iter);
03943          }
03944          qe->pr = NULL;
03945          snprintf(posstr, sizeof(posstr), "%d", qe->pos);
03946          pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
03947       } else {
03948          /* Renumber the people after us in the queue based on a new count */
03949          current->pos = ++pos;
03950          prev = current;
03951       }
03952    }
03953    ao2_unlock(q);
03954 
03955    /*If the queue is a realtime queue, check to see if it's still defined in real time*/
03956    if (q->realtime) {
03957       struct ast_variable *var;
03958       if (!(var = ast_load_realtime("queues", "name", q->name, SENTINEL))) {
03959          q->dead = 1;
03960       } else {
03961          ast_variables_destroy(var);
03962       }
03963    }
03964 
03965    if (q->dead) {
03966       /* It's dead and nobody is in it, so kill it */
03967       queues_t_unlink(queues, q, "Queue is now dead; remove it from the container");
03968    }
03969    /* unref the explicit ref earlier in the function */
03970    queue_t_unref(q, "Expire copied reference");
03971 }
03972 
03973 /*!
03974  * \internal
03975  * \brief Destroy the given callattempt structure and free it.
03976  * \since 1.8
03977  *
03978  * \param doomed callattempt structure to destroy.
03979  *
03980  * \return Nothing
03981  */
03982 static void callattempt_free(struct callattempt *doomed)
03983 {
03984    if (doomed->member) {
03985       ao2_ref(doomed->member, -1);
03986    }
03987    ast_party_connected_line_free(&doomed->connected);
03988    ast_free(doomed);
03989 }
03990 
03991 static void publish_dial_end_event(struct ast_channel *in, struct callattempt *outgoing, struct ast_channel *exception, const char *status)
03992 {
03993    struct callattempt *cur;
03994 
03995    for (cur = outgoing; cur; cur = cur->q_next) {
03996       if (cur->chan && cur->chan != exception) {
03997          ast_channel_publish_dial(in, cur->chan, NULL, status);
03998       }
03999    }
04000 }
04001 
04002 /*! \brief Hang up a list of outgoing calls */
04003 static void hangupcalls(struct queue_ent *qe, struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
04004 {
04005    struct callattempt *oo;
04006 
04007    while (outgoing) {
04008       /* If someone else answered the call we should indicate this in the CANCEL */
04009       /* Hangup any existing lines we have open */
04010       if (outgoing->chan && (outgoing->chan != exception)) {
04011          if (exception || cancel_answered_elsewhere) {
04012             ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
04013          }
04014          ast_channel_publish_dial(qe->chan, outgoing->chan, outgoing->interface, "CANCEL");
04015          ast_hangup(outgoing->chan);
04016       }
04017       oo = outgoing;
04018       outgoing = outgoing->q_next;
04019       ast_aoc_destroy_decoded(oo->aoc_s_rate_list);
04020       callattempt_free(oo);
04021    }
04022 }
04023 
04024 /*!
04025  * \brief Get the number of members available to accept a call.
04026  *
04027  * \note The queue passed in should be locked prior to this function call
04028  *
04029  * \param[in] q The queue for which we are couting the number of available members
04030  * \return Return the number of available members in queue q
04031  */
04032 static int num_available_members(struct call_queue *q)
04033 {
04034    struct member *mem;
04035    int avl = 0;
04036    struct ao2_iterator mem_iter;
04037 
04038    mem_iter = ao2_iterator_init(q->members, 0);
04039    while ((mem = ao2_iterator_next(&mem_iter))) {
04040 
04041       avl += is_member_available(q, mem);
04042       ao2_ref(mem, -1);
04043 
04044       /* If autofill is not enabled or if the queue's strategy is ringall, then
04045        * we really don't care about the number of available members so much as we
04046        * do that there is at least one available.
04047        *
04048        * In fact, we purposely will return from this function stating that only
04049        * one member is available if either of those conditions hold. That way,
04050        * functions which determine what action to take based on the number of available
04051        * members will operate properly. The reasoning is that even if multiple
04052        * members are available, only the head caller can actually be serviced.
04053        */
04054       if ((!q->autofill || q->strategy == QUEUE_STRATEGY_RINGALL) && avl) {
04055          break;
04056       }
04057    }
04058    ao2_iterator_destroy(&mem_iter);
04059 
04060    return avl;
04061 }
04062 
04063 /* traverse all defined queues which have calls waiting and contain this member
04064    return 0 if no other queue has precedence (higher weight) or 1 if found  */
04065 static int compare_weight(struct call_queue *rq, struct member *member)
04066 {
04067    struct call_queue *q;
04068    struct member *mem;
04069    int found = 0;
04070    struct ao2_iterator queue_iter;
04071 
04072    queue_iter = ao2_iterator_init(queues, 0);
04073    while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
04074       if (q == rq) { /* don't check myself, could deadlock */
04075          queue_t_unref(q, "Done with iterator");
04076          continue;
04077       }
04078       ao2_lock(q);
04079       if (q->count && q->members) {
04080          if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
04081             ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
04082             if (q->weight > rq->weight && q->count >= num_available_members(q)) {
04083                ast_debug(1, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count);
04084                found = 1;
04085             }
04086             ao2_ref(mem, -1);
04087          }
04088       }
04089       ao2_unlock(q);
04090       queue_t_unref(q, "Done with iterator");
04091       if (found) {
04092          break;
04093       }
04094    }
04095    ao2_iterator_destroy(&queue_iter);
04096    return found;
04097 }
04098 
04099 /*! \brief common hangup actions */
04100 static void do_hang(struct callattempt *o)
04101 {
04102    o->stillgoing = 0;
04103    ast_hangup(o->chan);
04104    o->chan = NULL;
04105 }
04106 
04107 /*!
04108  * \internal
04109  * \brief Check if the member status is available.
04110  *
04111  * \param status Member status to check if available.
04112  *
04113  * \retval non-zero if the member status is available.
04114  */
04115 static int member_status_available(int status)
04116 {
04117    return status == AST_DEVICE_NOT_INUSE || status == AST_DEVICE_UNKNOWN;
04118 }
04119 
04120 /*!
04121  * \internal
04122  * \brief Clear the member call pending flag.
04123  *
04124  * \param mem Queue member.
04125  *
04126  * \return Nothing
04127  */
04128 static void member_call_pending_clear(struct member *mem)
04129 {
04130    ao2_lock(mem);
04131    mem->call_pending = 0;
04132    ao2_unlock(mem);
04133 }
04134 
04135 /*!
04136  * \internal
04137  * \brief Set the member call pending flag.
04138  *
04139  * \param mem Queue member.
04140  *
04141  * \retval non-zero if call pending flag was already set.
04142  */
04143 static int member_call_pending_set(struct member *mem)
04144 {
04145    int old_pending;
04146 
04147    ao2_lock(mem);
04148    old_pending = mem->call_pending;
04149    mem->call_pending = 1;
04150    ao2_unlock(mem);
04151 
04152    return old_pending;
04153 }
04154 
04155 /*!
04156  * \internal
04157  * \brief Determine if can ring a queue entry.
04158  *
04159  * \param qe Queue entry to check.
04160  * \param call Member call attempt.
04161  *
04162  * \retval non-zero if an entry can be called.
04163  */
04164 static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
04165 {
04166    if (call->member->paused) {
04167       ast_debug(1, "%s paused, can't receive call\n", call->interface);
04168       return 0;
04169    }
04170 
04171    if (!call->member->ringinuse && !member_status_available(call->member->status)) {
04172       ast_debug(1, "%s not available, can't receive call\n", call->interface);
04173       return 0;
04174    }
04175 
04176    if ((call->lastqueue && call->lastqueue->wrapuptime && (time(NULL) - call->lastcall < call->lastqueue->wrapuptime))
04177       || (!call->lastqueue && qe->parent->wrapuptime && (time(NULL) - call->lastcall < qe->parent->wrapuptime))) {
04178       ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
04179          (call->lastqueue ? call->lastqueue->name : qe->parent->name),
04180          call->interface);
04181       return 0;
04182    }
04183 
04184    if (use_weight && compare_weight(qe->parent, call->member)) {
04185       ast_debug(1, "Priority queue delaying call to %s:%s\n",
04186          qe->parent->name, call->interface);
04187       return 0;
04188    }
04189 
04190    if (!call->member->ringinuse) {
04191       if (member_call_pending_set(call->member)) {
04192          ast_debug(1, "%s has another call pending, can't receive call\n",
04193             call->interface);
04194          return 0;
04195       }
04196 
04197       /*
04198        * The queue member is available.  Get current status to be sure
04199        * because the device state and extension state callbacks may
04200        * not have updated the status yet.
04201        */
04202       if (!member_status_available(get_queue_member_status(call->member))) {
04203          ast_debug(1, "%s actually not available, can't receive call\n",
04204             call->interface);
04205          member_call_pending_clear(call->member);
04206          return 0;
04207       }
04208    }
04209 
04210    return 1;
04211 }
04212 
04213 /*!
04214  * \brief Part 2 of ring_one
04215  *
04216  * Does error checking before attempting to request a channel and call a member.
04217  * This function is only called from ring_one().
04218  * Failure can occur if:
04219  * - Agent on call
04220  * - Agent is paused
04221  * - Wrapup time not expired
04222  * - Priority by another queue
04223  *
04224  * \retval 1 on success to reach a free agent
04225  * \retval 0 on failure to get agent.
04226  */
04227 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
04228 {
04229    int res;
04230    int status;
04231    char tech[256];
04232    char *location;
04233    const char *macrocontext, *macroexten;
04234    RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
04235 
04236    /* on entry here, we know that tmp->chan == NULL */
04237    if (!can_ring_entry(qe, tmp)) {
04238       tmp->stillgoing = 0;
04239       ++*busies;
04240       return 0;
04241    }
04242    ast_assert(tmp->member->ringinuse || tmp->member->call_pending);
04243 
04244    ast_copy_string(tech, tmp->interface, sizeof(tech));
04245    if ((location = strchr(tech, '/'))) {
04246       *location++ = '\0';
04247    } else {
04248       location = "";
04249    }
04250 
04251    /* Request the peer */
04252    tmp->chan = ast_request(tech, ast_channel_nativeformats(qe->chan), NULL, qe->chan, location, &status);
04253    if (!tmp->chan) {       /* If we can't, just go on to the next call */
04254       ao2_lock(qe->parent);
04255       qe->parent->rrpos++;
04256       qe->linpos++;
04257       ao2_unlock(qe->parent);
04258 
04259       member_call_pending_clear(tmp->member);
04260 
04261       publish_dial_end_event(qe->chan, tmp, NULL, "BUSY");
04262       tmp->stillgoing = 0;
04263       ++*busies;
04264       return 0;
04265    }
04266 
04267    ast_channel_lock_both(tmp->chan, qe->chan);
04268 
04269    ast_channel_req_accountcodes_precious(tmp->chan, qe->chan,
04270       AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
04271    if (qe->cancel_answered_elsewhere) {
04272       ast_channel_hangupcause_set(tmp->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
04273    }
04274    ast_channel_appl_set(tmp->chan, "AppQueue");
04275    ast_channel_data_set(tmp->chan, "(Outgoing Line)");
04276    memset(ast_channel_whentohangup(tmp->chan), 0, sizeof(*ast_channel_whentohangup(tmp->chan)));
04277 
04278    /* If the new channel has no callerid, try to guess what it should be */
04279    if (!ast_channel_caller(tmp->chan)->id.number.valid) {
04280       if (ast_channel_connected(qe->chan)->id.number.valid) {
04281          struct ast_party_caller caller;
04282 
04283          ast_party_caller_set_init(&caller, ast_channel_caller(tmp->chan));
04284          caller.id = ast_channel_connected(qe->chan)->id;
04285          caller.ani = ast_channel_connected(qe->chan)->ani;
04286          ast_channel_set_caller_event(tmp->chan, &caller, NULL);
04287       } else if (!ast_strlen_zero(ast_channel_dialed(qe->chan)->number.str)) {
04288          ast_set_callerid(tmp->chan, ast_channel_dialed(qe->chan)->number.str, NULL, NULL);
04289       } else if (!ast_strlen_zero(S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)))) {
04290          ast_set_callerid(tmp->chan, S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)), NULL, NULL);
04291       }
04292       tmp->dial_callerid_absent = 1;
04293    }
04294 
04295    ast_party_redirecting_copy(ast_channel_redirecting(tmp->chan), ast_channel_redirecting(qe->chan));
04296 
04297    ast_channel_dialed(tmp->chan)->transit_network_select = ast_channel_dialed(qe->chan)->transit_network_select;
04298 
04299    ast_connected_line_copy_from_caller(ast_channel_connected(tmp->chan), ast_channel_caller(qe->chan));
04300 
04301    /* Inherit specially named variables from parent channel */
04302    ast_channel_inherit_variables(qe->chan, tmp->chan);
04303    ast_channel_datastore_inherit(qe->chan, tmp->chan);
04304 
04305    /* Presense of ADSI CPE on outgoing channel follows ours */
04306    ast_channel_adsicpe_set(tmp->chan, ast_channel_adsicpe(qe->chan));
04307 
04308    /* Inherit context and extension */
04309    macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
04310    ast_channel_dialcontext_set(tmp->chan, ast_strlen_zero(macrocontext) ? ast_channel_context(qe->chan) : macrocontext);
04311    macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
04312    if (!ast_strlen_zero(macroexten)) {
04313       ast_channel_exten_set(tmp->chan, macroexten);
04314    } else {
04315       ast_channel_exten_set(tmp->chan, ast_channel_exten(qe->chan));
04316    }
04317 
04318    ast_channel_unlock(tmp->chan);
04319    ast_channel_unlock(qe->chan);
04320 
04321    /* Place the call, but don't wait on the answer */
04322    if ((res = ast_call(tmp->chan, location, 0))) {
04323       /* Again, keep going even if there's an error */
04324       ast_verb(3, "Couldn't call %s\n", tmp->interface);
04325       do_hang(tmp);
04326       member_call_pending_clear(tmp->member);
04327       ++*busies;
04328       return 0;
04329    }
04330 
04331    ast_channel_lock_both(tmp->chan, qe->chan);
04332 
04333    blob = ast_json_pack("{s: s, s: s, s: s}",
04334               "Queue", qe->parent->name,
04335               "Interface", tmp->interface,
04336               "MemberName", tmp->member->membername);
04337    queue_publish_multi_channel_blob(qe->chan, tmp->chan, queue_agent_called_type(), blob);
04338 
04339    ast_channel_publish_dial(qe->chan, tmp->chan, tmp->interface, NULL);
04340 
04341    ast_channel_unlock(tmp->chan);
04342    ast_channel_unlock(qe->chan);
04343 
04344    ast_verb(3, "Called %s\n", tmp->interface);
04345 
04346    member_call_pending_clear(tmp->member);
04347    return 1;
04348 }
04349 
04350 /*! \brief find the entry with the best metric, or NULL */
04351 static struct callattempt *find_best(struct callattempt *outgoing)
04352 {
04353    struct callattempt *best = NULL, *cur;
04354 
04355    for (cur = outgoing; cur; cur = cur->q_next) {
04356       if (cur->stillgoing &&              /* Not already done */
04357          !cur->chan &&              /* Isn't already going */
04358          (!best || cur->metric < best->metric)) {     /* We haven't found one yet, or it's better */
04359          best = cur;
04360       }
04361    }
04362 
04363    return best;
04364 }
04365 
04366 /*!
04367  * \brief Place a call to a queue member.
04368  *
04369  * Once metrics have been calculated for each member, this function is used
04370  * to place a call to the appropriate member (or members). The low-level
04371  * channel-handling and error detection is handled in ring_entry
04372  *
04373  * \retval 1 if a member was called successfully
04374  * \retval 0 otherwise
04375  */
04376 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
04377 {
04378    int ret = 0;
04379 
04380    while (ret == 0) {
04381       struct callattempt *best = find_best(outgoing);
04382       if (!best) {
04383          ast_debug(1, "Nobody left to try ringing in queue\n");
04384          break;
04385       }
04386       if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
04387          struct callattempt *cur;
04388          /* Ring everyone who shares this best metric (for ringall) */
04389          for (cur = outgoing; cur; cur = cur->q_next) {
04390             if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
04391                ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
04392                ret |= ring_entry(qe, cur, busies);
04393             }
04394          }
04395       } else {
04396          /* Ring just the best channel */
04397          ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
04398          ret = ring_entry(qe, best, busies);
04399       }
04400 
04401       /* If we have timed out, break out */
04402       if (qe->expire && (time(NULL) >= qe->expire)) {
04403          ast_debug(1, "Queue timed out while ringing members.\n");
04404          ret = 0;
04405          break;
04406       }
04407    }
04408 
04409    return ret;
04410 }
04411 
04412 /*! \brief Search for best metric and add to Round Robbin queue */
04413 static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
04414 {
04415    struct callattempt *best = find_best(outgoing);
04416 
04417    if (best) {
04418       /* Ring just the best channel */
04419       ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
04420       qe->parent->rrpos = best->metric % 1000;
04421    } else {
04422       /* Just increment rrpos */
04423       if (qe->parent->wrapped) {
04424          /* No more channels, start over */
04425          qe->parent->rrpos = 0;
04426       } else {
04427          /* Prioritize next entry */
04428          qe->parent->rrpos++;
04429       }
04430    }
04431    qe->parent->wrapped = 0;
04432 
04433    return 0;
04434 }
04435 
04436 /*! \brief Search for best metric and add to Linear queue */
04437 static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
04438 {
04439    struct callattempt *best = find_best(outgoing);
04440 
04441    if (best) {
04442       /* Ring just the best channel */
04443       ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
04444       qe->linpos = best->metric % 1000;
04445    } else {
04446       /* Just increment rrpos */
04447       if (qe->linwrapped) {
04448          /* No more channels, start over */
04449          qe->linpos = 0;
04450       } else {
04451          /* Prioritize next entry */
04452          qe->linpos++;
04453       }
04454    }
04455    qe->linwrapped = 0;
04456 
04457    return 0;
04458 }
04459 
04460 /*! \brief Playback announcement to queued members if period has elapsed */
04461 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
04462 {
04463    int res = 0;
04464    time_t now;
04465 
04466    /* Get the current time */
04467    time(&now);
04468 
04469    /* Check to see if it is time to announce */
04470    if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency) {
04471       return 0;
04472    }
04473 
04474    /* Stop the music on hold so we can play our own file */
04475    if (ringing) {
04476       ast_indicate(qe->chan,-1);
04477    } else {
04478       ast_moh_stop(qe->chan);
04479    }
04480 
04481    ast_verb(3, "Playing periodic announcement\n");
04482 
04483    if (qe->parent->randomperiodicannounce && qe->parent->numperiodicannounce) {
04484       qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
04485    } else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce ||
04486       ast_str_strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]) == 0) {
04487       qe->last_periodic_announce_sound = 0;
04488    }
04489 
04490    /* play the announcement */
04491    res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]));
04492 
04493    if (res > 0 && !valid_exit(qe, res)) {
04494       res = 0;
04495    }
04496 
04497    /* Resume Music on Hold if the caller is going to stay in the queue */
04498    if (!res) {
04499       if (ringing) {
04500          ast_indicate(qe->chan, AST_CONTROL_RINGING);
04501       } else {
04502          ast_moh_start(qe->chan, qe->moh, NULL);
04503       }
04504    }
04505 
04506    /* update last_periodic_announce_time */
04507    if (qe->parent->relativeperiodicannounce) {
04508       time(&qe->last_periodic_announce_time);
04509    } else {
04510       qe->last_periodic_announce_time = now;
04511    }
04512 
04513    /* Update the current periodic announcement to the next announcement */
04514    if (!qe->parent->randomperiodicannounce) {
04515       qe->last_periodic_announce_sound++;
04516    }
04517 
04518    return res;
04519 }
04520 
04521 /*! \brief Record that a caller gave up on waiting in queue */
04522 static void record_abandoned(struct queue_ent *qe)
04523 {
04524    RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
04525 
04526    set_queue_variables(qe->parent, qe->chan);
04527    ao2_lock(qe->parent);
04528    blob = ast_json_pack("{s: s, s: i, s: i, s: i}",
04529               "Queue", qe->parent->name,
04530               "Position", qe->pos,
04531               "OriginalPosition", qe->opos,
04532               "HoldTime", (int)(time(NULL) - qe->start));
04533 
04534    qe->parent->callsabandoned++;
04535    ao2_unlock(qe->parent);
04536 
04537    ast_channel_publish_cached_blob(qe->chan, queue_caller_abandon_type(), blob);
04538 }
04539 
04540 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
04541 static void rna(int rnatime, struct queue_ent *qe, struct ast_channel *peer, char *interface, char *membername, int autopause)
04542 {
04543    RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
04544 
04545    ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
04546 
04547    /* Stop ringing, and resume MOH if specified */
04548    if (qe->ring_when_ringing) {
04549       ast_indicate(qe->chan, -1);
04550       ast_moh_start(qe->chan, qe->moh, NULL);
04551    }
04552 
04553    blob = ast_json_pack("{s: s, s: s, s: s, s: i}",
04554               "Queue", qe->parent->name,
04555               "Interface", interface,
04556               "MemberName", membername,
04557               "RingTime", rnatime);
04558    queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_ringnoanswer_type(), blob);
04559 
04560    ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), membername, "RINGNOANSWER", "%d", rnatime);
04561    if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && autopause) {
04562       if (qe->parent->autopausedelay > 0) {
04563          struct member *mem;
04564          ao2_lock(qe->parent);
04565          if ((mem = interface_exists(qe->parent, interface))) {
04566             time_t idletime = time(&idletime)-mem->lastcall;
04567             if ((mem->lastcall != 0) && (qe->parent->autopausedelay > idletime)) {
04568                ao2_unlock(qe->parent);
04569                ao2_ref(mem, -1);
04570                return;
04571             }
04572             ao2_ref(mem, -1);
04573          }
04574          ao2_unlock(qe->parent);
04575       }
04576       if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
04577          if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
04578             ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
04579                interface, qe->parent->name);
04580          } else {
04581             ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
04582          }
04583       } else {
04584          /* If queue autopause is mode all, just don't send any queue to stop.
04585          * the function will stop in all queues */
04586          if (!set_member_paused("", interface, "Auto-Pause", 1)) {
04587             ast_verb(3, "Auto-Pausing Queue Member %s in all queues since they failed to answer on queue %s.\n",
04588                   interface, qe->parent->name);
04589          } else {
04590                ast_verb(3, "Failed to pause Queue Member %s in all queues!\n", interface);
04591          }
04592       }
04593    }
04594    return;
04595 }
04596 
04597 #define AST_MAX_WATCHERS 256
04598 /*!
04599  * \brief Wait for a member to answer the call
04600  *
04601  * \param[in] qe the queue_ent corresponding to the caller in the queue
04602  * \param[in] outgoing the list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
04603  * \param[in] to the amount of time (in milliseconds) to wait for a response
04604  * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
04605  * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
04606  * \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
04607  * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
04608  *
04609  * \todo eventually all call forward logic should be intergerated into and replaced by ast_call_forward()
04610  */
04611 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int ringing)
04612 {
04613    const char *queue = qe->parent->name;
04614    struct callattempt *o, *start = NULL, *prev = NULL;
04615    int status;
04616    int numbusies = prebusies;
04617    int numnochan = 0;
04618    int stillgoing = 0;
04619    int orig = *to;
04620    struct ast_frame *f;
04621    struct callattempt *peer = NULL;
04622    struct ast_channel *winner;
04623    struct ast_channel *in = qe->chan;
04624    char on[80] = "";
04625    char membername[80] = "";
04626    long starttime = 0;
04627    long endtime = 0;
04628 #ifdef HAVE_EPOLL
04629    struct callattempt *epollo;
04630 #endif
04631    struct ast_party_connected_line connected_caller;
04632    char *inchan_name;
04633    struct timeval start_time_tv = ast_tvnow();
04634 
04635    ast_party_connected_line_init(&connected_caller);
04636 
04637    ast_channel_lock(qe->chan);
04638    inchan_name = ast_strdupa(ast_channel_name(qe->chan));
04639    ast_channel_unlock(qe->chan);
04640 
04641    starttime = (long) time(NULL);
04642 #ifdef HAVE_EPOLL
04643    for (epollo = outgoing; epollo; epollo = epollo->q_next) {
04644       if (epollo->chan) {
04645          ast_poll_channel_add(in, epollo->chan);
04646       }
04647    }
04648 #endif
04649 
04650    while ((*to = ast_remaining_ms(start_time_tv, orig)) && !peer) {
04651       int numlines, retry, pos = 1;
04652       struct ast_channel *watchers[AST_MAX_WATCHERS];
04653       watchers[0] = in;
04654       start = NULL;
04655 
04656       for (retry = 0; retry < 2; retry++) {
04657          numlines = 0;
04658          for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
04659             if (o->stillgoing) { /* Keep track of important channels */
04660                stillgoing = 1;
04661                if (o->chan) {
04662                   if (pos < AST_MAX_WATCHERS) {
04663                      watchers[pos++] = o->chan;
04664                   }
04665                   if (!start) {
04666                      start = o;
04667                   } else {
04668                      prev->call_next = o;
04669                   }
04670                   prev = o;
04671                }
04672             } else if (prev) {
04673                prev->call_next = NULL;
04674             }
04675             numlines++;
04676          }
04677          if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
04678             (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */) {
04679             break;
04680          }
04681          /* On "ringall" strategy we only move to the next penalty level
04682             when *all* ringing phones are done in the current penalty level */
04683          ring_one(qe, outgoing, &numbusies);
04684          /* and retry... */
04685       }
04686       if (pos == 1 /* not found */) {
04687          if (numlines == (numbusies + numnochan)) {
04688             ast_debug(1, "Everyone is busy at this time\n");
04689          } else {
04690             ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
04691          }
04692          *to = 0;
04693          return NULL;
04694       }
04695 
04696       /* Poll for events from both the incoming channel as well as any outgoing channels */
04697       winner = ast_waitfor_n(watchers, pos, to);
04698 
04699       /* Service all of the outgoing channels */
04700       for (o = start; o; o = o->call_next) {
04701          /* We go with a fixed buffer here instead of using ast_strdupa. Using
04702           * ast_strdupa in a loop like this one can cause a stack overflow
04703           */
04704          char ochan_name[AST_CHANNEL_NAME];
04705 
04706          if (o->chan) {
04707             ast_channel_lock(o->chan);
04708             ast_copy_string(ochan_name, ast_channel_name(o->chan), sizeof(ochan_name));
04709             ast_channel_unlock(o->chan);
04710          }
04711          if (o->stillgoing && (o->chan) &&  (ast_channel_state(o->chan) == AST_STATE_UP)) {
04712             if (!peer) {
04713                ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
04714                if (!o->block_connected_update) {
04715                   if (o->pending_connected_update) {
04716                      if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
04717                         ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
04718                         ast_channel_update_connected_line(in, &o->connected, NULL);
04719                      }
04720                   } else if (!o->dial_callerid_absent) {
04721                      ast_channel_lock(o->chan);
04722                      ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(o->chan));
04723                      ast_channel_unlock(o->chan);
04724                      connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
04725                      if (ast_channel_connected_line_sub(o->chan, in, &connected_caller, 0) &&
04726                         ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
04727                         ast_channel_update_connected_line(in, &connected_caller, NULL);
04728                      }
04729                      ast_party_connected_line_free(&connected_caller);
04730                   }
04731                }
04732                if (o->aoc_s_rate_list) {
04733                   size_t encoded_size;
04734                   struct ast_aoc_encoded *encoded;
04735                   if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
04736                      ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
04737                      ast_aoc_destroy_encoded(encoded);
04738                   }
04739                }
04740                peer = o;
04741             }
04742          } else if (o->chan && (o->chan == winner)) {
04743 
04744             ast_copy_string(on, o->member->interface, sizeof(on));
04745             ast_copy_string(membername, o->member->membername, sizeof(membername));
04746 
04747             /* Before processing channel, go ahead and check for forwarding */
04748             if (!ast_strlen_zero(ast_channel_call_forward(o->chan)) && !forwardsallowed) {
04749                ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, ast_channel_call_forward(o->chan));
04750                numnochan++;
04751                do_hang(o);
04752                winner = NULL;
04753                continue;
04754             } else if (!ast_strlen_zero(ast_channel_call_forward(o->chan))) {
04755                struct ast_channel *original = o->chan;
04756                char tmpchan[256];
04757                char *stuff;
04758                char *tech;
04759 
04760                ast_copy_string(tmpchan, ast_channel_call_forward(o->chan), sizeof(tmpchan));
04761                if ((stuff = strchr(tmpchan, '/'))) {
04762                   *stuff++ = '\0';
04763                   tech = tmpchan;
04764                } else {
04765                   snprintf(tmpchan, sizeof(tmpchan), "%s@%s", ast_channel_call_forward(o->chan), ast_channel_context(o->chan));
04766                   stuff = tmpchan;
04767                   tech = "Local";
04768                }
04769                if (!strcasecmp(tech, "Local")) {
04770                   /*
04771                    * Drop the connected line update block for local channels since
04772                    * this is going to run dialplan and the user can change his
04773                    * mind about what connected line information he wants to send.
04774                    */
04775                   o->block_connected_update = 0;
04776                }
04777 
04778                ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
04779                /* Setup parameters */
04780                o->chan = ast_request(tech, ast_channel_nativeformats(in), NULL, in, stuff, &status);
04781                if (!o->chan) {
04782                   ast_log(LOG_NOTICE,
04783                      "Forwarding failed to create channel to dial '%s/%s'\n",
04784                      tech, stuff);
04785                   o->stillgoing = 0;
04786                   numnochan++;
04787                } else {
04788                   ast_channel_lock_both(o->chan, original);
04789                   ast_party_redirecting_copy(ast_channel_redirecting(o->chan),
04790                      ast_channel_redirecting(original));
04791                   ast_channel_unlock(o->chan);
04792                   ast_channel_unlock(original);
04793 
04794                   ast_channel_lock_both(o->chan, in);
04795                   ast_channel_inherit_variables(in, o->chan);
04796                   ast_channel_datastore_inherit(in, o->chan);
04797 
04798                   if (o->pending_connected_update) {
04799                      /*
04800                       * Re-seed the callattempt's connected line information with
04801                       * previously acquired connected line info from the queued
04802                       * channel.  The previously acquired connected line info could
04803                       * have been set through the CONNECTED_LINE dialplan function.
04804                       */
04805                      o->pending_connected_update = 0;
04806                      ast_party_connected_line_copy(&o->connected, ast_channel_connected(in));
04807                   }
04808 
04809                   ast_channel_req_accountcodes(o->chan, in, AST_CHANNEL_REQUESTOR_BRIDGE_PEER);
04810 
04811                   if (!ast_channel_redirecting(o->chan)->from.number.valid
04812                      || ast_strlen_zero(ast_channel_redirecting(o->chan)->from.number.str)) {
04813                      /*
04814                       * The call was not previously redirected so it is
04815                       * now redirected from this number.
04816                       */
04817                      ast_party_number_free(&ast_channel_redirecting(o->chan)->from.number);
04818                      ast_party_number_init(&ast_channel_redirecting(o->chan)->from.number);
04819                      ast_channel_redirecting(o->chan)->from.number.valid = 1;
04820                      ast_channel_redirecting(o->chan)->from.number.str =
04821                         ast_strdup(S_OR(ast_channel_macroexten(in), ast_channel_exten(in)));
04822                   }
04823 
04824                   ast_channel_dialed(o->chan)->transit_network_select = ast_channel_dialed(in)->transit_network_select;
04825 
04826                   o->dial_callerid_absent = !ast_channel_caller(o->chan)->id.number.valid
04827                      || ast_strlen_zero(ast_channel_caller(o->chan)->id.number.str);
04828                   ast_connected_line_copy_from_caller(ast_channel_connected(o->chan),
04829                      ast_channel_caller(in));
04830 
04831                   ast_channel_unlock(in);
04832                   if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL
04833                      && !o->block_connected_update) {
04834                      struct ast_party_redirecting redirecting;
04835 
04836                      /*
04837                       * Redirecting updates to the caller make sense only on single
04838                       * call at a time strategies.
04839                       *
04840                       * We must unlock o->chan before calling
04841                       * ast_channel_redirecting_macro, because we put o->chan into
04842                       * autoservice there.  That is pretty much a guaranteed
04843                       * deadlock.  This is why the handling of o->chan's lock may
04844                       * seem a bit unusual here.
04845                       */
04846                      ast_party_redirecting_init(&redirecting);
04847                      ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(o->chan));
04848                      ast_channel_unlock(o->chan);
04849                      if (ast_channel_redirecting_sub(o->chan, in, &redirecting, 0) &&
04850                         ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0)) {
04851                         ast_channel_update_redirecting(in, &redirecting, NULL);
04852                      }
04853                      ast_party_redirecting_free(&redirecting);
04854                   } else {
04855                      ast_channel_unlock(o->chan);
04856                   }
04857 
04858                   if (ast_call(o->chan, stuff, 0)) {
04859                      ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
04860                         tech, stuff);
04861                      do_hang(o);
04862                      numnochan++;
04863                   }
04864                }
04865 
04866                ast_channel_publish_dial(qe->chan, o->chan, stuff, NULL);
04867                ast_channel_publish_dial_forward(qe->chan, original, o->chan, NULL,
04868                   "CANCEL", ast_channel_call_forward(original));
04869 
04870                /* Hangup the original channel now, in case we needed it */
04871                ast_hangup(winner);
04872                continue;
04873             }
04874             f = ast_read(winner);
04875             if (f) {
04876                if (f->frametype == AST_FRAME_CONTROL) {
04877                   switch (f->subclass.integer) {
04878                   case AST_CONTROL_ANSWER:
04879                      /* This is our guy if someone answered. */
04880                      if (!peer) {
04881                         ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
04882                         ast_channel_publish_dial(qe->chan, o->chan, on, "ANSWER");
04883                         publish_dial_end_event(qe->chan, outgoing, o->chan, "CANCEL");
04884                         if (!o->block_connected_update) {
04885                            if (o->pending_connected_update) {
04886                               if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
04887                                  ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
04888                                  ast_channel_update_connected_line(in, &o->connected, NULL);
04889                               }
04890                            } else if (!o->dial_callerid_absent) {
04891                               ast_channel_lock(o->chan);
04892                               ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(o->chan));
04893                               ast_channel_unlock(o->chan);
04894                               connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
04895                               if (ast_channel_connected_line_sub(o->chan, in, &connected_caller, 0) &&
04896                                  ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
04897                                  ast_channel_update_connected_line(in, &connected_caller, NULL);
04898                               }
04899                               ast_party_connected_line_free(&connected_caller);
04900                            }
04901                         }
04902                         if (o->aoc_s_rate_list) {
04903                            size_t encoded_size;
04904                            struct ast_aoc_encoded *encoded;
04905                            if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
04906                               ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
04907                               ast_aoc_destroy_encoded(encoded);
04908                            }
04909                         }
04910                         peer = o;
04911                      }
04912                      break;
04913                   case AST_CONTROL_BUSY:
04914                      ast_verb(3, "%s is busy\n", ochan_name);
04915                      ast_channel_publish_dial(qe->chan, o->chan, on, "BUSY");
04916                      endtime = (long) time(NULL);
04917                      endtime -= starttime;
04918                      rna(endtime * 1000, qe, o->chan, on, membername, qe->parent->autopausebusy);
04919                      do_hang(o);
04920                      if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
04921                         if (qe->parent->timeoutrestart) {
04922                            start_time_tv = ast_tvnow();
04923                         }
04924                         /* Have enough time for a queue member to answer? */
04925                         if (ast_remaining_ms(start_time_tv, orig) > 500) {
04926                            ring_one(qe, outgoing, &numbusies);
04927                            starttime = (long) time(NULL);
04928                         }
04929                      }
04930                      numbusies++;
04931                      break;
04932                   case AST_CONTROL_CONGESTION:
04933                      ast_verb(3, "%s is circuit-busy\n", ochan_name);
04934                      ast_channel_publish_dial(qe->chan, o->chan, on, "CONGESTION");
04935                      endtime = (long) time(NULL);
04936                      endtime -= starttime;
04937                      rna(endtime * 1000, qe, o->chan, on, membername, qe->parent->autopauseunavail);
04938                      do_hang(o);
04939                      if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
04940                         if (qe->parent->timeoutrestart) {
04941                            start_time_tv = ast_tvnow();
04942                         }
04943                         if (ast_remaining_ms(start_time_tv, orig) > 500) {
04944                            ring_one(qe, outgoing, &numbusies);
04945                            starttime = (long) time(NULL);
04946                         }
04947                      }
04948                      numbusies++;
04949                      break;
04950                   case AST_CONTROL_RINGING:
04951                      ast_verb(3, "%s is ringing\n", ochan_name);
04952 
04953                      /* Start ring indication when the channel is ringing, if specified */
04954                      if (qe->ring_when_ringing) {
04955                         ast_moh_stop(qe->chan);
04956                         ast_indicate(qe->chan, AST_CONTROL_RINGING);
04957                      }
04958                      break;
04959                   case AST_CONTROL_OFFHOOK:
04960                      /* Ignore going off hook */
04961                      break;
04962                   case AST_CONTROL_CONNECTED_LINE:
04963                      if (o->block_connected_update) {
04964                         ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
04965                         break;
04966                      }
04967                      if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
04968                         struct ast_party_connected_line connected;
04969 
04970                         ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
04971                         ast_party_connected_line_set_init(&connected, &o->connected);
04972                         ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
04973                         ast_party_connected_line_set(&o->connected, &connected, NULL);
04974                         ast_party_connected_line_free(&connected);
04975                         o->pending_connected_update = 1;
04976                         break;
04977                      }
04978 
04979                      /*
04980                       * Prevent using the CallerID from the outgoing channel since we
04981                       * got a connected line update from it.
04982                       */
04983                      o->dial_callerid_absent = 1;
04984 
04985                      if (ast_channel_connected_line_sub(o->chan, in, f, 1) &&
04986                         ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
04987                         ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
04988                      }
04989                      break;
04990                   case AST_CONTROL_AOC:
04991                      {
04992                         struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
04993                         if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) {
04994                            ast_aoc_destroy_decoded(o->aoc_s_rate_list);
04995                            o->aoc_s_rate_list = decoded;
04996                         } else {
04997                            ast_aoc_destroy_decoded(decoded);
04998                         }
04999                      }
05000                      break;
05001                   case AST_CONTROL_REDIRECTING:
05002                      if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
05003                         /*
05004                          * Redirecting updates to the caller make sense only on single
05005                          * call at a time strategies.
05006                          */
05007                         break;
05008                      }
05009                      if (o->block_connected_update) {
05010                         ast_verb(3, "Redirecting update to %s prevented\n",
05011                            inchan_name);
05012                         break;
05013                      }
05014                      ast_verb(3, "%s redirecting info has changed, passing it to %s\n",
05015                         ochan_name, inchan_name);
05016                      if (ast_channel_redirecting_sub(o->chan, in, f, 1) &&
05017                         ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {
05018                         ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
05019                      }
05020                      break;
05021                   case AST_CONTROL_PVT_CAUSE_CODE:
05022                      ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);
05023                      break;
05024                   default:
05025                      ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
05026                      break;
05027                   }
05028                }
05029                ast_frfree(f);
05030             } else { /* ast_read() returned NULL */
05031                endtime = (long) time(NULL) - starttime;
05032                ast_channel_publish_dial(qe->chan, o->chan, on, "NOANSWER");
05033                rna(endtime * 1000, qe, o->chan, on, membername, 1);
05034                do_hang(o);
05035                if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
05036                   if (qe->parent->timeoutrestart) {
05037                      start_time_tv = ast_tvnow();
05038                   }
05039                   if (ast_remaining_ms(start_time_tv, orig) > 500) {
05040                      ring_one(qe, outgoing, &numbusies);
05041                      starttime = (long) time(NULL);
05042                   }
05043                }
05044             }
05045          }
05046       }
05047 
05048       /* If we received an event from the caller, deal with it. */
05049       if (winner == in) {
05050          f = ast_read(in);
05051          if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
05052             /* Got hung up */
05053             *to = -1;
05054             publish_dial_end_event(in, outgoing, NULL, "CANCEL");
05055             if (f) {
05056                if (f->data.uint32) {
05057                   ast_channel_hangupcause_set(in, f->data.uint32);
05058                }
05059                ast_frfree(f);
05060             }
05061             return NULL;
05062          }
05063 
05064          if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
05065             ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
05066             *to = 0;
05067             publish_dial_end_event(in, outgoing, NULL, "CANCEL");
05068             ast_frfree(f);
05069             return NULL;
05070          }
05071          if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
05072             ast_verb(3, "User pressed digit: %c\n", f->subclass.integer);
05073             *to = 0;
05074             publish_dial_end_event(in, outgoing, NULL, "CANCEL");
05075             *digit = f->subclass.integer;
05076             ast_frfree(f);
05077             return NULL;
05078          }
05079 
05080          /* Send the frame from the in channel to all outgoing channels. */
05081          for (o = start; o; o = o->call_next) {
05082             if (!o->stillgoing || !o->chan) {
05083                /* This outgoing channel has died so don't send the frame to it. */
05084                continue;
05085             }
05086             switch (f->frametype) {
05087             case AST_FRAME_CONTROL:
05088                switch (f->subclass.integer) {
05089                case AST_CONTROL_CONNECTED_LINE:
05090                   if (ast_channel_connected_line_sub(in, o->chan, f, 1) &&
05091                      ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) {
05092                      ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
05093                   }
05094                   break;
05095                case AST_CONTROL_REDIRECTING:
05096                   if (ast_channel_redirecting_sub(in, o->chan, f, 1) &&
05097                      ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) {
05098                      ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
05099                   }
05100                   break;
05101                default:
05102                   /* We are not going to do anything with this frame. */
05103                   goto skip_frame;
05104                }
05105                break;
05106             default:
05107                /* We are not going to do anything with this frame. */
05108                goto skip_frame;
05109             }
05110          }
05111 skip_frame:;
05112 
05113          ast_frfree(f);
05114       }
05115    }
05116 
05117    /* Make a position announcement, if enabled */
05118    if (qe->parent->announcefrequency && qe->parent->announce_to_first_user) {
05119       say_position(qe, ringing);
05120    }
05121 
05122    /* Make a periodic announcement, if enabled */
05123    if (qe->parent->periodicannouncefrequency && qe->parent->announce_to_first_user) {
05124       say_periodic_announcement(qe, ringing);
05125    }
05126 
05127    if (!*to) {
05128       for (o = start; o; o = o->call_next) {
05129          if (o->chan) {
05130             rna(orig, qe, o->chan, o->interface, o->member->membername, 1);
05131          }
05132       }
05133 
05134       publish_dial_end_event(qe->chan, outgoing, NULL, "NOANSWER");
05135    }
05136 
05137 #ifdef HAVE_EPOLL
05138    for (epollo = outgoing; epollo; epollo = epollo->q_next) {
05139       if (epollo->chan) {
05140          ast_poll_channel_del(in, epollo->chan);
05141       }
05142    }
05143 #endif
05144 
05145    return peer;
05146 }
05147 
05148 /*!
05149  * \brief Check if we should start attempting to call queue members.
05150  *
05151  * A simple process, really. Count the number of members who are available
05152  * to take our call and then see if we are in a position in the queue at
05153  * which a member could accept our call.
05154  *
05155  * \param[in] qe The caller who wants to know if it is his turn
05156  * \retval 0 It is not our turn
05157  * \retval 1 It is our turn
05158  */
05159 static int is_our_turn(struct queue_ent *qe)
05160 {
05161    struct queue_ent *ch;
05162    int res;
05163    int avl;
05164    int idx = 0;
05165    /* This needs a lock. How many members are available to be served? */
05166    ao2_lock(qe->parent);
05167 
05168    avl = num_available_members(qe->parent);
05169 
05170    ch = qe->parent->head;
05171 
05172    ast_debug(1, "There %s %d available %s.\n", avl != 1 ? "are" : "is", avl, avl != 1 ? "members" : "member");
05173 
05174    while ((idx < avl) && (ch) && (ch != qe)) {
05175       if (!ch->pending) {
05176          idx++;
05177       }
05178       ch = ch->next;
05179    }
05180 
05181    ao2_unlock(qe->parent);
05182    /* If the queue entry is within avl [the number of available members] calls from the top ...
05183     * Autofill and position check added to support autofill=no (as only calls
05184     * from the front of the queue are valid when autofill is disabled)
05185     */
05186    if (ch && idx < avl && (qe->parent->autofill || qe->pos == 1)) {
05187       ast_debug(1, "It's our turn (%s).\n", ast_channel_name(qe->chan));
05188       res = 1;
05189    } else {
05190       ast_debug(1, "It's not our turn (%s).\n", ast_channel_name(qe->chan));
05191       res = 0;
05192    }
05193 
05194    return res;
05195 }
05196 
05197 /*!
05198  * \brief update rules for queues
05199  *
05200  * Calculate min/max penalties making sure if relative they stay within bounds.
05201  * Update queues penalty and set dialplan vars, goto next list entry.
05202 */
05203 static void update_qe_rule(struct queue_ent *qe)
05204 {
05205    int max_penalty = INT_MAX;
05206 
05207    if (qe->max_penalty != INT_MAX) {
05208       char max_penalty_str[20];
05209 
05210       if (qe->pr->max_relative) {
05211          max_penalty = qe->max_penalty + qe->pr->max_value;
05212       } else {
05213          max_penalty = qe->pr->max_value;
05214       }
05215 
05216       /* a relative change to the penalty could put it below 0 */
05217       if (max_penalty < 0) {
05218          max_penalty = 0;
05219       }
05220 
05221       snprintf(max_penalty_str, sizeof(max_penalty_str), "%d", max_penalty);
05222       pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
05223       qe->max_penalty = max_penalty;
05224       ast_debug(3, "Setting max penalty to %d for caller %s since %d seconds have elapsed\n",
05225          qe->max_penalty, ast_channel_name(qe->chan), qe->pr->time);
05226    }
05227 
05228    if (qe->min_penalty != INT_MAX) {
05229       char min_penalty_str[20];
05230       int min_penalty;
05231 
05232       if (qe->pr->min_relative) {
05233          min_penalty = qe->min_penalty + qe->pr->min_value;
05234       } else {
05235          min_penalty = qe->pr->min_value;
05236       }
05237 
05238       /* a relative change to the penalty could put it below 0 */
05239       if (min_penalty < 0) {
05240          min_penalty = 0;
05241       }
05242 
05243       if (max_penalty != INT_MAX && min_penalty > max_penalty) {
05244          min_penalty = max_penalty;
05245       }
05246 
05247       snprintf(min_penalty_str, sizeof(min_penalty_str), "%d", min_penalty);
05248       pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
05249       qe->min_penalty = min_penalty;
05250       ast_debug(3, "Setting min penalty to %d for caller %s since %d seconds have elapsed\n",
05251          qe->min_penalty, ast_channel_name(qe->chan), qe->pr->time);
05252    }
05253 
05254    qe->pr = AST_LIST_NEXT(qe->pr, list);
05255 }
05256 
05257 /*! \brief The waiting areas for callers who are not actively calling members
05258  *
05259  * This function is one large loop. This function will return if a caller
05260  * either exits the queue or it becomes that caller's turn to attempt calling
05261  * queue members. Inside the loop, we service the caller with periodic announcements,
05262  * holdtime announcements, etc. as configured in queues.conf
05263  *
05264  * \retval  0 if the caller's turn has arrived
05265  * \retval -1 if the caller should exit the queue.
05266  */
05267 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
05268 {
05269    int res = 0;
05270 
05271    /* This is the holding pen for callers 2 through maxlen */
05272    for (;;) {
05273 
05274       if (is_our_turn(qe)) {
05275          break;
05276       }
05277 
05278       /* If we have timed out, break out */
05279       if (qe->expire && (time(NULL) >= qe->expire)) {
05280          *reason = QUEUE_TIMEOUT;
05281          break;
05282       }
05283 
05284       if (qe->parent->leavewhenempty) {
05285          int status = 0;
05286 
05287          if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->parent->leavewhenempty, 0))) {
05288             *reason = QUEUE_LEAVEEMPTY;
05289             ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) (time(NULL) - qe->start));
05290             leave_queue(qe);
05291             break;
05292          }
05293       }
05294 
05295       /* Make a position announcement, if enabled */
05296       if (qe->parent->announcefrequency &&
05297          (res = say_position(qe,ringing))) {
05298          break;
05299       }
05300 
05301       /* If we have timed out, break out */
05302       if (qe->expire && (time(NULL) >= qe->expire)) {
05303          *reason = QUEUE_TIMEOUT;
05304          break;
05305       }
05306 
05307       /* Make a periodic announcement, if enabled */
05308       if (qe->parent->periodicannouncefrequency &&
05309          (res = say_periodic_announcement(qe,ringing)))
05310          break;
05311 
05312       /* see if we need to move to the next penalty level for this queue */
05313       while (qe->pr && ((time(NULL) - qe->start) >= qe->pr->time)) {
05314          update_qe_rule(qe);
05315       }
05316 
05317       /* If we have timed out, break out */
05318       if (qe->expire && (time(NULL) >= qe->expire)) {
05319          *reason = QUEUE_TIMEOUT;
05320          break;
05321       }
05322 
05323       /* Wait a second before checking again */
05324       if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
05325          if (res > 0 && !valid_exit(qe, res)) {
05326             res = 0;
05327          } else {
05328             break;
05329          }
05330       }
05331 
05332       /* If we have timed out, break out */
05333       if (qe->expire && (time(NULL) >= qe->expire)) {
05334          *reason = QUEUE_TIMEOUT;
05335          break;
05336       }
05337    }
05338 
05339    return res;
05340 }
05341 
05342 /*!
05343  * \brief update the queue status
05344  * \retval Always 0
05345 */
05346 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, int newtalktime)
05347 {
05348    int oldtalktime;
05349 
05350    struct member *mem;
05351    struct call_queue *qtmp;
05352    struct ao2_iterator queue_iter;
05353 
05354    if (shared_lastcall) {
05355       queue_iter = ao2_iterator_init(queues, 0);
05356       while ((qtmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
05357          ao2_lock(qtmp);
05358          if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
05359             time(&mem->lastcall);
05360             mem->calls++;
05361             mem->lastqueue = q;
05362             ao2_ref(mem, -1);
05363          }
05364          ao2_unlock(qtmp);
05365          queue_t_unref(qtmp, "Done with iterator");
05366       }
05367       ao2_iterator_destroy(&queue_iter);
05368    } else {
05369       ao2_lock(q);
05370       time(&member->lastcall);
05371       member->calls++;
05372       member->lastqueue = q;
05373       ao2_unlock(q);
05374    }
05375    ao2_lock(q);
05376    q->callscompleted++;
05377    if (callcompletedinsl) {
05378       q->callscompletedinsl++;
05379    }
05380    /* Calculate talktime using the same exponential average as holdtime code*/
05381    oldtalktime = q->talktime;
05382    q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
05383    ao2_unlock(q);
05384    return 0;
05385 }
05386 
05387 /*! \brief Calculate the metric of each member in the outgoing callattempts
05388  *
05389  * A numeric metric is given to each member depending on the ring strategy used
05390  * by the queue. Members with lower metrics will be called before members with
05391  * higher metrics
05392  * \retval -1 if penalties are exceeded
05393  * \retval 0 otherwise
05394  */
05395 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
05396 {
05397    /* disregarding penalty on too few members? */
05398    int membercount = ao2_container_count(q->members);
05399    unsigned char usepenalty = (membercount <= q->penaltymemberslimit) ? 0 : 1;
05400 
05401    if (usepenalty) {
05402       if ((qe->max_penalty != INT_MAX && mem->penalty > qe->max_penalty) ||
05403          (qe->min_penalty != INT_MAX && mem->penalty < qe->min_penalty)) {
05404          return -1;
05405       }
05406    } else {
05407       ast_debug(1, "Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
05408            membercount, q->penaltymemberslimit);
05409    }
05410 
05411    switch (q->strategy) {
05412    case QUEUE_STRATEGY_RINGALL:
05413       /* Everyone equal, except for penalty */
05414       tmp->metric = mem->penalty * 1000000 * usepenalty;
05415       break;
05416    case QUEUE_STRATEGY_LINEAR:
05417       if (pos < qe->linpos) {
05418          tmp->metric = 1000 + pos;
05419       } else {
05420          if (pos > qe->linpos) {
05421             /* Indicate there is another priority */
05422             qe->linwrapped = 1;
05423          }
05424          tmp->metric = pos;
05425       }
05426       tmp->metric += mem->penalty * 1000000 * usepenalty;
05427       break;
05428    case QUEUE_STRATEGY_RRORDERED:
05429    case QUEUE_STRATEGY_RRMEMORY:
05430       pos = mem->queuepos;
05431       if (pos < q->rrpos) {
05432          tmp->metric = 1000 + pos;
05433       } else {
05434          if (pos > q->rrpos) {
05435             /* Indicate there is another priority */
05436             q->wrapped = 1;
05437          }
05438          tmp->metric = pos;
05439       }
05440       tmp->metric += mem->penalty * 1000000 * usepenalty;
05441       break;
05442    case QUEUE_STRATEGY_RANDOM:
05443       tmp->metric = ast_random() % 1000;
05444       tmp->metric += mem->penalty * 1000000 * usepenalty;
05445       break;
05446    case QUEUE_STRATEGY_WRANDOM:
05447       tmp->metric = ast_random() % ((1 + mem->penalty) * 1000);
05448       break;
05449    case QUEUE_STRATEGY_FEWESTCALLS:
05450       tmp->metric = mem->calls;
05451       tmp->metric += mem->penalty * 1000000 * usepenalty;
05452       break;
05453    case QUEUE_STRATEGY_LEASTRECENT:
05454       if (!mem->lastcall) {
05455          tmp->metric = 0;
05456       } else {
05457          tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
05458       }
05459       tmp->metric += mem->penalty * 1000000 * usepenalty;
05460       break;
05461    default:
05462       ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
05463       break;
05464    }
05465    return 0;
05466 }
05467 
05468 enum agent_complete_reason {
05469    CALLER,
05470    AGENT,
05471    TRANSFER
05472 };
05473 
05474 /*! \brief Send out AMI message with member call completion status information */
05475 static void send_agent_complete(const char *queuename, struct ast_channel_snapshot *caller,
05476    struct ast_channel_snapshot *peer, const struct member *member, time_t holdstart,
05477    time_t callstart, enum agent_complete_reason rsn)
05478 {
05479    const char *reason = NULL; /* silence dumb compilers */
05480    RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
05481 
05482    switch (rsn) {
05483    case CALLER:
05484       reason = "caller";
05485       break;
05486    case AGENT:
05487       reason = "agent";
05488       break;
05489    case TRANSFER:
05490       reason = "transfer";
05491       break;
05492    }
05493 
05494    blob = ast_json_pack("{s: s, s: s, s: s, s: i, s: i, s: s}",
05495               "Queue", queuename,
05496               "Interface", member->interface,
05497               "MemberName", member->membername,
05498               "HoldTime", (long)(callstart - holdstart),
05499               "TalkTime", (long)(time(NULL) - callstart),
05500               "Reason", reason);
05501 
05502    queue_publish_multi_channel_snapshot_blob(ast_queue_topic(queuename), caller, peer,
05503          queue_agent_complete_type(), blob);
05504 }
05505 
05506 static void queue_agent_cb(void *userdata, struct stasis_subscription *sub,
05507       struct stasis_message *msg)
05508 {
05509    struct ast_channel_blob *agent_blob;
05510 
05511    agent_blob = stasis_message_data(msg);
05512 
05513    if (ast_channel_agent_login_type() == stasis_message_type(msg)) {
05514       ast_queue_log("NONE", agent_blob->snapshot->uniqueid,
05515          ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),
05516          "AGENTLOGIN", "%s", agent_blob->snapshot->name);
05517    } else if (ast_channel_agent_logoff_type() == stasis_message_type(msg)) {
05518       ast_queue_log("NONE", agent_blob->snapshot->uniqueid,
05519          ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),
05520          "AGENTLOGOFF", "%s|%ld", agent_blob->snapshot->name,
05521          (long) ast_json_integer_get(ast_json_object_get(agent_blob->blob, "logintime")));
05522    }
05523 }
05524 
05525 /*!
05526  * \brief Structure representing relevant data during a local channel optimization
05527  *
05528  * The reason we care about local channel optimizations is that we want to be able
05529  * to accurately report when the caller and queue member have stopped talking to
05530  * each other. A local channel optimization can cause it to appear that the conversation
05531  * has stopped immediately after it has begun. By tracking that the relevant channels
05532  * to monitor have changed due to a local channel optimization, we can give accurate
05533  * reports.
05534  *
05535  * Local channel optimizations for queues are restricted from their normal operation.
05536  * Bridges created by queues can only be the destination of local channel optimizations,
05537  * not the source. In addition, move-swap local channel optimizations are the only
05538  * permitted types of local channel optimization.
05539  *
05540  * This data is populated when we are told that a local channel optimization begin
05541  * is occurring. When we get told the optimization has ended successfully, we then
05542  * apply the data here into the queue_stasis_data.
05543  */
05544 struct local_optimization {
05545    /*! The uniqueid of the channel that will be taking the place of the caller or member */
05546    const char *source_chan_uniqueid;
05547    /*! Indication of whether we think there is a local channel optimization in progress */
05548    int in_progress;
05549    /*! The identifier for this local channel optimization */
05550    unsigned int id;
05551 };
05552 
05553 /*!
05554  * \brief User data for stasis subscriptions used for queue calls.
05555  *
05556  * app_queue subscribes to channel and bridge events for all bridged calls.
05557  * app_queue cares about the following events:
05558  *
05559  * \li bridge enter: To determine the unique ID of the bridge created for the call.
05560  * \li blind transfer: To send an appropriate agent complete event.
05561  * \li attended transfer: To send an appropriate agent complete event.
05562  * \li local optimization: To update caller and member unique IDs for the call.
05563  * \li hangup: To send an appropriate agent complete event.
05564  *
05565  * The stasis subscriptions last until we determine that the caller and the member
05566  * are no longer bridged with each other.
05567  */
05568 struct queue_stasis_data {
05569    AST_DECLARE_STRING_FIELDS(
05570       /*! The unique ID of the caller's channel. */
05571       AST_STRING_FIELD(caller_uniqueid);
05572       /*! The unique ID of the queue member's channel */
05573       AST_STRING_FIELD(member_uniqueid);
05574       /*! The unique ID of the bridge created by the queue */
05575       AST_STRING_FIELD(bridge_uniqueid);
05576    );
05577    /*! The relevant queue */
05578    struct call_queue *queue;
05579    /*! The queue member that has answered the call */
05580    struct member *member;
05581    /*! The time at which the caller entered the queue. Start of the caller's hold time */
05582    time_t holdstart;
05583    /*! The time at which the member answered the call. */
05584    time_t starttime;
05585    /*! The original position of the caller when he entered the queue */
05586    int caller_pos;
05587    /*! Indication if the call was answered within the configured service level of the queue */
05588    int callcompletedinsl;
05589    /*! Indicates if the stasis subscriptions are shutting down */
05590    int dying;
05591    /*! The stasis message router for bridge events */
05592    struct stasis_message_router *bridge_router;
05593    /*! The stasis message router for channel events */
05594    struct stasis_message_router *channel_router;
05595    /*! Local channel optimization details for the caller */
05596    struct local_optimization caller_optimize;
05597    /*! Local channel optimization details for the member */
05598    struct local_optimization member_optimize;
05599 };
05600 
05601 /*!
05602  * \internal
05603  * \brief Free memory for a queue_stasis_data
05604  */
05605 static void queue_stasis_data_destructor(void *obj)
05606 {
05607    struct queue_stasis_data *queue_data = obj;
05608 
05609    /* This can only happen if refcounts for this object have got severely messed up */
05610    ast_assert(queue_data->bridge_router == NULL);
05611    ast_assert(queue_data->channel_router == NULL);
05612 
05613    ao2_cleanup(queue_data->member);
05614    queue_unref(queue_data->queue);
05615    ast_string_field_free_memory(queue_data);
05616 }
05617 
05618 /*!
05619  * \internal
05620  * \brief End all stasis subscriptions on a queue_stasis_data
05621  */
05622 static void remove_stasis_subscriptions(struct queue_stasis_data *queue_data)
05623 {
05624    SCOPED_AO2LOCK(lock, queue_data);
05625 
05626    queue_data->dying = 1;
05627    stasis_message_router_unsubscribe(queue_data->bridge_router);
05628    queue_data->bridge_router = NULL;
05629    stasis_message_router_unsubscribe(queue_data->channel_router);
05630    queue_data->channel_router = NULL;
05631 }
05632 
05633 /*!
05634  * \internal
05635  * \brief Allocate a queue_stasis_data and initialize its data.
05636  */
05637 static struct queue_stasis_data *queue_stasis_data_alloc(struct queue_ent *qe,
05638       struct ast_channel *peer, struct member *mem, time_t holdstart,
05639       time_t starttime, int callcompletedinsl)
05640 {
05641    struct queue_stasis_data *queue_data;
05642 
05643    queue_data = ao2_alloc(sizeof(*queue_data), queue_stasis_data_destructor);
05644    if (!queue_data) {
05645       return NULL;
05646    }
05647 
05648    if (ast_string_field_init(queue_data, 64)) {
05649       ao2_cleanup(queue_data);
05650       return NULL;
05651    }
05652 
05653    ast_string_field_set(queue_data, caller_uniqueid, ast_channel_uniqueid(qe->chan));
05654    ast_string_field_set(queue_data, member_uniqueid, ast_channel_uniqueid(peer));
05655    queue_data->queue = queue_ref(qe->parent);
05656    queue_data->starttime = starttime;
05657    queue_data->holdstart = holdstart;
05658    queue_data->callcompletedinsl = callcompletedinsl;
05659    queue_data->caller_pos = qe->opos;
05660    ao2_ref(mem, +1);
05661    queue_data->member = mem;
05662    return queue_data;
05663 }
05664 
05665 /*!
05666  * \internal
05667  * \brief Log an attended transfer in the queue log.
05668  *
05669  * Attended transfer queue log messages vary based on the method by which the
05670  * attended transfer was completed.
05671  *
05672  * \param queue_data Data pertaining to the particular call in the queue.
05673  * \param caller The channel snapshot for the caller channel in the queue.
05674  * \param atxfer_msg The stasis attended transfer message data.
05675  */
05676 static void log_attended_transfer(struct queue_stasis_data *queue_data, struct ast_channel_snapshot *caller,
05677       struct ast_attended_transfer_message *atxfer_msg)
05678 {
05679    RAII_VAR(struct ast_str *, transfer_str, ast_str_create(32), ast_free);
05680 
05681    if (!transfer_str) {
05682       ast_log(LOG_WARNING, "Unable to log attended transfer to queue log\n");
05683       return;
05684    }
05685 
05686    switch (atxfer_msg->dest_type) {
05687    case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
05688       ast_str_set(&transfer_str, 0, "BRIDGE|%s", atxfer_msg->dest.bridge);
05689       break;
05690    case AST_ATTENDED_TRANSFER_DEST_APP:
05691    case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
05692       ast_str_set(&transfer_str, 0, "APP|%s", atxfer_msg->dest.app);
05693       break;
05694    case AST_ATTENDED_TRANSFER_DEST_LINK:
05695       ast_str_set(&transfer_str, 0, "LINK|%s|%s", atxfer_msg->dest.links[0]->name,
05696             atxfer_msg->dest.links[1]->name);
05697       break;
05698    case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
05699    case AST_ATTENDED_TRANSFER_DEST_FAIL:
05700       /* Threeways are headed off and should not be logged here */
05701       ast_assert(0);
05702       return;
05703    }
05704 
05705    ast_queue_log(queue_data->queue->name, caller->uniqueid, queue_data->member->membername, "ATTENDEDTRANSFER", "%s|%ld|%ld|%d",
05706          ast_str_buffer(transfer_str),
05707          (long) (queue_data->starttime - queue_data->holdstart),
05708          (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
05709 }
05710 
05711 /*!
05712  * \internal
05713  * \brief Handle a stasis bridge enter event.
05714  *
05715  * We track this particular event in order to learn what bridge
05716  * was created for the queue call.
05717  *
05718  * \param userdata Data pertaining to the particular call in the queue.
05719  * \param sub The stasis subscription on which the message occurred.
05720  * \param topic The topic for this event.
05721  * \param msg The stasis message for the bridge enter event
05722  */
05723 static void handle_bridge_enter(void *userdata, struct stasis_subscription *sub,
05724       struct stasis_message *msg)
05725 {
05726    struct queue_stasis_data *queue_data = userdata;
05727    struct ast_bridge_blob *enter_blob = stasis_message_data(msg);
05728 
05729    if (queue_data->dying) {
05730       return;
05731    }
05732 
05733    if (!ast_strlen_zero(queue_data->bridge_uniqueid)) {
05734       return;
05735    }
05736 
05737    if (!strcmp(enter_blob->channel->uniqueid, queue_data->caller_uniqueid)) {
05738       ast_string_field_set(queue_data, bridge_uniqueid,
05739             enter_blob->bridge->uniqueid);
05740       ast_debug(3, "Detected entry of caller channel %s into bridge %s\n",
05741             enter_blob->channel->name, queue_data->bridge_uniqueid);
05742    }
05743 }
05744 
05745 /*!
05746  * \brief Handle a blind transfer event
05747  *
05748  * This event is important in order to be able to log the end of the
05749  * call to the queue log and to stasis.
05750  *
05751  * \param userdata Data pertaining to the particular call in the queue.
05752  * \param sub The stasis subscription on which the message occurred.
05753  * \param topic The topic for this event.
05754  * \param msg The stasis message for the blind transfer event
05755  */
05756 static void handle_blind_transfer(void *userdata, struct stasis_subscription *sub,
05757       struct stasis_message *msg)
05758 {
05759    struct queue_stasis_data *queue_data = userdata;
05760    struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
05761    const char *exten;
05762    const char *context;
05763    RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
05764    RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
05765 
05766    if (queue_data->dying) {
05767       return;
05768    }
05769 
05770    if (transfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS) {
05771       return;
05772    }
05773 
05774    ao2_lock(queue_data);
05775 
05776    if (ast_strlen_zero(queue_data->bridge_uniqueid) ||
05777          strcmp(queue_data->bridge_uniqueid, transfer_msg->bridge->uniqueid)) {
05778       ao2_unlock(queue_data);
05779       return;
05780    }
05781 
05782    caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
05783    member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
05784 
05785    ao2_unlock(queue_data);
05786 
05787    exten = transfer_msg->exten;
05788    context = transfer_msg->context;
05789 
05790    ast_debug(3, "Detected blind transfer in queue %s\n", queue_data->queue->name);
05791    ast_queue_log(queue_data->queue->name, caller_snapshot->uniqueid, queue_data->member->membername,
05792          "BLINDTRANSFER", "%s|%s|%ld|%ld|%d",
05793          exten, context,
05794          (long) (queue_data->starttime - queue_data->holdstart),
05795          (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
05796 
05797    send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
05798          queue_data->holdstart, queue_data->starttime, TRANSFER);
05799    update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
05800          time(NULL) - queue_data->starttime);
05801    remove_stasis_subscriptions(queue_data);
05802 }
05803 
05804 /*!
05805  * \brief Handle an attended transfer event
05806  *
05807  * This event is important in order to be able to log the end of the
05808  * call to the queue log and to stasis.
05809  *
05810  * \param userdata Data pertaining to the particular call in the queue.
05811  * \param sub The stasis subscription on which the message occurred.
05812  * \param topic The topic for this event.
05813  * \param msg The stasis message for the attended transfer event.
05814  */
05815 static void handle_attended_transfer(void *userdata, struct stasis_subscription *sub,
05816       struct stasis_message *msg)
05817 {
05818    struct queue_stasis_data *queue_data = userdata;
05819    struct ast_attended_transfer_message *atxfer_msg = stasis_message_data(msg);
05820    RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
05821    RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
05822 
05823    if (queue_data->dying) {
05824       return;
05825    }
05826 
05827    if (atxfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS ||
05828          atxfer_msg->dest_type == AST_ATTENDED_TRANSFER_DEST_THREEWAY) {
05829       return;
05830    }
05831 
05832    ao2_lock(queue_data);
05833 
05834    if (ast_strlen_zero(queue_data->bridge_uniqueid)) {
05835       ao2_unlock(queue_data);
05836       return;
05837    }
05838 
05839    if ((!atxfer_msg->to_transferee.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
05840                atxfer_msg->to_transferee.bridge_snapshot->uniqueid)) &&
05841           (!atxfer_msg->to_transfer_target.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
05842              atxfer_msg->to_transfer_target.bridge_snapshot->uniqueid))) {
05843       ao2_unlock(queue_data);
05844       return;
05845    }
05846 
05847    caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
05848    member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
05849 
05850    ao2_unlock(queue_data);
05851 
05852    ast_debug(3, "Detected attended transfer in queue %s\n", queue_data->queue->name);
05853 
05854    log_attended_transfer(queue_data, caller_snapshot, atxfer_msg);
05855 
05856    send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
05857          queue_data->holdstart, queue_data->starttime, TRANSFER);
05858    update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
05859          time(NULL) - queue_data->starttime);
05860    remove_stasis_subscriptions(queue_data);
05861 }
05862 
05863 /*!
05864  * \internal
05865  * \brief Callback for all stasis bridge events
05866  *
05867  * Based on the event and what bridge it is on, the task is farmed out to relevant
05868  * subroutines for further processing.
05869  */
05870 static void queue_bridge_cb(void *userdata, struct stasis_subscription *sub,
05871       struct stasis_message *msg)
05872 {
05873    if (stasis_subscription_final_message(sub, msg)) {
05874       ao2_cleanup(userdata);
05875    }
05876 }
05877 
05878 /*!
05879  * \internal
05880  * \brief Handler for the beginning of a local channel optimization
05881  *
05882  * This method gathers data relevant to the local channel optimization and stores
05883  * it to be used once the local optimization completes.
05884  *
05885  * \param userdata Data pertaining to the particular call in the queue.
05886  * \param sub The stasis subscription on which the message occurred.
05887  * \param topic The topic for this event.
05888  * \param msg The stasis message for the local optimization begin event
05889  */
05890 static void handle_local_optimization_begin(void *userdata, struct stasis_subscription *sub,
05891       struct stasis_message *msg)
05892 {
05893    struct queue_stasis_data *queue_data = userdata;
05894    struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
05895    struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
05896    struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
05897    struct ast_channel_snapshot *source = ast_multi_channel_blob_get_channel(optimization_blob, "source");
05898    struct local_optimization *optimization;
05899    unsigned int id;
05900    SCOPED_AO2LOCK(lock, queue_data);
05901 
05902    if (queue_data->dying) {
05903       return;
05904    }
05905 
05906    if (!strcmp(local_one->uniqueid, queue_data->member_uniqueid)) {
05907       optimization = &queue_data->member_optimize;
05908    } else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {
05909       optimization = &queue_data->caller_optimize;
05910    } else {
05911       return;
05912    }
05913 
05914    /* We only allow move-swap optimizations, so there had BETTER be a source */
05915    ast_assert(source != NULL);
05916 
05917    optimization->source_chan_uniqueid = ast_strdup(source->uniqueid);
05918    if (!optimization->source_chan_uniqueid) {
05919       ast_log(LOG_ERROR, "Unable to track local channel optimization for channel %s. Expect further errors\n", local_one->name);
05920       return;
05921    }
05922    id = ast_json_integer_get(ast_json_object_get(ast_multi_channel_blob_get_json(optimization_blob), "id"));
05923 
05924    optimization->id = id;
05925    optimization->in_progress = 1;
05926 }
05927 
05928 /*!
05929  * \internal
05930  * \brief Handler for the end of a local channel optimization
05931  *
05932  * This method takes the data gathered during the local channel optimization begin
05933  * event and applies it to the queue stasis data appropriately. This generally involves
05934  * updating the caller or member unique ID with the channel that is taking the place of
05935  * the previous caller or member.
05936  *
05937  * \param userdata Data pertaining to the particular call in the queue.
05938  * \param sub The stasis subscription on which the message occurred.
05939  * \param topic The topic for this event.
05940  * \param msg The stasis message for the local optimization end event
05941  */
05942 static void handle_local_optimization_end(void *userdata, struct stasis_subscription *sub,
05943       struct stasis_message *msg)
05944 {
05945    struct queue_stasis_data *queue_data = userdata;
05946    struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
05947    struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
05948    struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
05949    struct local_optimization *optimization;
05950    int is_caller;
05951    unsigned int id;
05952    SCOPED_AO2LOCK(lock, queue_data);
05953 
05954    if (queue_data->dying) {
05955       return;
05956    }
05957 
05958    if (!strcmp(local_one->uniqueid, queue_data->member_uniqueid)) {
05959       optimization = &queue_data->member_optimize;
05960       is_caller = 0;
05961    } else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {
05962       optimization = &queue_data->caller_optimize;
05963       is_caller = 1;
05964    } else {
05965       return;
05966    }
05967 
05968    id = ast_json_integer_get(ast_json_object_get(ast_multi_channel_blob_get_json(optimization_blob), "id"));
05969 
05970    if (!optimization->in_progress) {
05971       ast_log(LOG_WARNING, "Told of a local optimization end when we had no previous begin\n");
05972       return;
05973    }
05974 
05975    if (id != optimization->id) {
05976       ast_log(LOG_WARNING, "Local optimization end event ID does not match begin (%u != %u)\n",
05977             id, optimization->id);
05978       return;
05979    }
05980 
05981    if (is_caller) {
05982       ast_debug(3, "Local optimization: Changing queue caller uniqueid from %s to %s\n",
05983             queue_data->caller_uniqueid, optimization->source_chan_uniqueid);
05984       ast_string_field_set(queue_data, caller_uniqueid, optimization->source_chan_uniqueid);
05985    } else {
05986       ast_debug(3, "Local optimization: Changing queue member uniqueid from %s to %s\n",
05987             queue_data->member_uniqueid, optimization->source_chan_uniqueid);
05988       ast_string_field_set(queue_data, member_uniqueid, optimization->source_chan_uniqueid);
05989    }
05990 
05991    optimization->in_progress = 0;
05992 }
05993 
05994 /*!
05995  * \internal
05996  * \brief Handler for hangup stasis event
05997  *
05998  * This is how we determine that the caller or member has hung up and the call
05999  * has ended. An appropriate queue log and stasis message are raised in this
06000  * callback.
06001  *
06002  * \param userdata Data pertaining to the particular call in the queue.
06003  * \param sub The stasis subscription on which the message occurred.
06004  * \param topic The topic for this event.
06005  * \param msg The stasis message for the hangup event.
06006  */
06007 static void handle_hangup(void *userdata, struct stasis_subscription *sub,
06008       struct stasis_message *msg)
06009 {
06010    struct queue_stasis_data *queue_data = userdata;
06011    struct ast_channel_blob *channel_blob = stasis_message_data(msg);
06012    RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
06013    RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
06014    RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
06015    enum agent_complete_reason reason;
06016 
06017    if (queue_data->dying) {
06018       return;
06019    }
06020 
06021    ao2_lock(queue_data);
06022 
06023    if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->caller_uniqueid)) {
06024       reason = CALLER;
06025    } else if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->member_uniqueid)) {
06026       reason = AGENT;
06027    } else {
06028       ao2_unlock(queue_data);
06029       return;
06030    }
06031 
06032    chan = ast_channel_get_by_name(channel_blob->snapshot->name);
06033    if (chan && ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME)) {
06034       /* Channel that is hanging up is doing it as part of a transfer.
06035        * We'll get a transfer event later
06036        */
06037       ao2_unlock(queue_data);
06038       return;
06039    }
06040 
06041    caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
06042    member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
06043 
06044    ao2_unlock(queue_data);
06045 
06046    ast_debug(3, "Detected hangup of queue %s channel %s\n", reason == CALLER ? "caller" : "member",
06047          channel_blob->snapshot->name);
06048 
06049    ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername,
06050          reason == CALLER ? "COMPLETECALLER" : "COMPLETEAGENT", "%ld|%ld|%d",
06051       (long) (queue_data->starttime - queue_data->holdstart),
06052       (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
06053 
06054    send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
06055          queue_data->holdstart, queue_data->starttime, reason);
06056    update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
06057          time(NULL) - queue_data->starttime);
06058    remove_stasis_subscriptions(queue_data);
06059 }
06060 
06061 /*!
06062  * \internal
06063  * \brief Callback for all stasis channel events
06064  *
06065  * Based on the event and the channels involved, the work is farmed out into
06066  * subroutines for further processing.
06067  */
06068 static void queue_channel_cb(void *userdata, struct stasis_subscription *sub,
06069       struct stasis_message *msg)
06070 {
06071    if (stasis_subscription_final_message(sub, msg)) {
06072       ao2_cleanup(userdata);
06073    }
06074 }
06075 
06076 /*!
06077  * \internal
06078  * \brief Create stasis subscriptions for a particular call in the queue.
06079  *
06080  * These subscriptions are created once the call has been answered. The subscriptions
06081  * are put in place so that call progress may be tracked. Once the call can be determined
06082  * to have ended, then messages are logged to the queue log and stasis events are emitted.
06083  *
06084  * \param qe The queue entry representing the caller
06085  * \param peer The channel that has answered the call
06086  * \param mem The queue member that answered the call
06087  * \param holdstart The time at which the caller entered the queue
06088  * \param starttime The time at which the call was answered
06089  * \param callcompletedinsl Indicates if the call was answered within the configured service level of the queue.
06090  * \retval 0 Success
06091  * \retval non-zero Failure
06092  */
06093 static int setup_stasis_subs(struct queue_ent *qe, struct ast_channel *peer, struct member *mem,
06094       time_t holdstart, time_t starttime, int callcompletedinsl)
06095 {
06096    struct queue_stasis_data *queue_data = queue_stasis_data_alloc(qe, peer, mem, holdstart, starttime, callcompletedinsl);
06097 
06098    if (!queue_data) {
06099       return -1;
06100    }
06101 
06102    queue_data->bridge_router = stasis_message_router_create_pool(ast_bridge_topic_all());
06103    if (!queue_data->bridge_router) {
06104       ao2_ref(queue_data, -1);
06105       return -1;
06106    }
06107 
06108    stasis_message_router_add(queue_data->bridge_router, ast_channel_entered_bridge_type(),
06109          handle_bridge_enter, queue_data);
06110    stasis_message_router_add(queue_data->bridge_router, ast_blind_transfer_type(),
06111          handle_blind_transfer, queue_data);
06112    stasis_message_router_add(queue_data->bridge_router, ast_attended_transfer_type(),
06113          handle_attended_transfer, queue_data);
06114    stasis_message_router_set_default(queue_data->bridge_router,
06115          queue_bridge_cb, queue_data);
06116 
06117    queue_data->channel_router = stasis_message_router_create_pool(ast_channel_topic_all());
06118    if (!queue_data->channel_router) {
06119       /* Unsubscribing from the bridge router will remove the only ref of queue_data,
06120        * thus beginning the destruction process
06121        */
06122       stasis_message_router_unsubscribe(queue_data->bridge_router);
06123       queue_data->bridge_router = NULL;
06124       return -1;
06125    }
06126 
06127    ao2_ref(queue_data, +1);
06128    stasis_message_router_add(queue_data->channel_router, ast_local_optimization_begin_type(),
06129          handle_local_optimization_begin, queue_data);
06130    stasis_message_router_add(queue_data->channel_router, ast_local_optimization_end_type(),
06131          handle_local_optimization_end, queue_data);
06132    stasis_message_router_add(queue_data->channel_router, ast_channel_hangup_request_type(),
06133          handle_hangup, queue_data);
06134    stasis_message_router_set_default(queue_data->channel_router,
06135          queue_channel_cb, queue_data);
06136 
06137    return 0;
06138 }
06139 
06140 struct queue_end_bridge {
06141    struct call_queue *q;
06142    struct ast_channel *chan;
06143 };
06144 
06145 static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
06146 {
06147    struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
06148    ao2_ref(qeb, +1);
06149    qeb->chan = originator;
06150 }
06151 
06152 static void end_bridge_callback(void *data)
06153 {
06154    struct queue_end_bridge *qeb = data;
06155    struct call_queue *q = qeb->q;
06156    struct ast_channel *chan = qeb->chan;
06157 
06158    if (ao2_ref(qeb, -1) == 1) {
06159       set_queue_variables(q, chan);
06160       /* This unrefs the reference we made in try_calling when we allocated qeb */
06161       queue_t_unref(q, "Expire bridge_config reference");
06162    }
06163 }
06164 
06165 /*!
06166  * \internal
06167  * \brief Setup the after bridge goto location on the peer.
06168  * \since 12.0.0
06169  *
06170  * \param chan Calling channel for bridge.
06171  * \param peer Peer channel for bridge.
06172  * \param opts Dialing option flags.
06173  * \param opt_args Dialing option argument strings.
06174  *
06175  * \return Nothing
06176  */
06177 static void setup_peer_after_bridge_goto(struct ast_channel *chan, struct ast_channel *peer, struct ast_flags *opts, char *opt_args[])
06178 {
06179    const char *context;
06180    const char *extension;
06181    int priority;
06182 
06183    if (ast_test_flag(opts, OPT_CALLEE_GO_ON)) {
06184       ast_channel_lock(chan);
06185       context = ast_strdupa(ast_channel_context(chan));
06186       extension = ast_strdupa(ast_channel_exten(chan));
06187       priority = ast_channel_priority(chan);
06188       ast_channel_unlock(chan);
06189       ast_bridge_set_after_go_on(peer, context, extension, priority,
06190          opt_args[OPT_ARG_CALLEE_GO_ON]);
06191    }
06192 }
06193 
06194 static void escape_and_substitute(struct ast_channel *chan, const char *input,
06195       char *output, size_t size)
06196 {
06197    const char *m = input;
06198    char escaped[size];
06199    char *p;
06200 
06201    for (p = escaped; p < escaped + size - 1; p++, m++) {
06202       switch (*m) {
06203       case '^':
06204          if (*(m + 1) == '{') {
06205             *p = '$';
06206          }
06207          break;
06208       case ',':
06209          *p++ = '\\';
06210          /* Fall through */
06211       default:
06212          *p = *m;
06213       }
06214       if (*m == '\0')
06215          break;
06216    }
06217 
06218    if (p == escaped + size) {
06219       escaped[size - 1] = '\0';
06220    }
06221 
06222    pbx_substitute_variables_helper(chan, escaped, output, size - 1);
06223 }
06224 
06225 static void setup_mixmonitor(struct queue_ent *qe, const char *filename)
06226 {
06227    char escaped_filename[256];
06228    char file_with_ext[256];
06229    char mixmonargs[1512];
06230    char escaped_monitor_exec[1024];
06231    const char *monitor_options;
06232    const char *monitor_exec;
06233 
06234    escaped_monitor_exec[0] = '\0';
06235 
06236    if (filename) {
06237       escape_and_substitute(qe->chan, filename, escaped_filename, sizeof(escaped_filename));
06238    } else {
06239       ast_copy_string(escaped_filename, ast_channel_uniqueid(qe->chan), sizeof(escaped_filename));
06240    }
06241 
06242    ast_channel_lock(qe->chan);
06243    if ((monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC"))) {
06244       monitor_exec = ast_strdupa(monitor_exec);
06245    }
06246    if ((monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS"))) {
06247       monitor_options = ast_strdupa(monitor_options);
06248    } else {
06249       monitor_options = "";
06250    }
06251    ast_channel_unlock(qe->chan);
06252 
06253    if (monitor_exec) {
06254       escape_and_substitute(qe->chan, monitor_exec, escaped_monitor_exec, sizeof(escaped_monitor_exec));
06255    }
06256 
06257    snprintf(file_with_ext, sizeof(file_with_ext), "%s.%s", escaped_filename, qe->parent->monfmt);
06258 
06259    if (!ast_strlen_zero(escaped_monitor_exec)) {
06260       snprintf(mixmonargs, sizeof(mixmonargs), "b%s,%s", monitor_options, escaped_monitor_exec);
06261    } else {
06262       snprintf(mixmonargs, sizeof(mixmonargs), "b%s", monitor_options);
06263    }
06264 
06265    ast_debug(1, "Arguments being passed to MixMonitor: %s,%s\n", file_with_ext, mixmonargs);
06266 
06267    if (ast_start_mixmonitor(qe->chan, file_with_ext, mixmonargs)) {
06268       ast_log(LOG_WARNING, "Unable to start mixmonitor. Is the MixMonitor app loaded?\n");
06269    }
06270 }
06271 
06272 /*!
06273  * \internal
06274  * \brief A large function which calls members, updates statistics, and bridges the caller and a member
06275  *
06276  * Here is the process of this function
06277  * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
06278  * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member. During this
06279  *    iteration, we also check the dialed_interfaces datastore to see if we have already attempted calling this
06280  *    member. If we have, we do not create a callattempt. This is in place to prevent call forwarding loops. Also
06281  *    during each iteration, we call calc_metric to determine which members should be rung when.
06282  * 3. Call ring_one to place a call to the appropriate member(s)
06283  * 4. Call wait_for_answer to wait for an answer. If no one answers, return.
06284  * 5. Take care of any holdtime announcements, member delays, or other options which occur after a call has been answered.
06285  * 6. Start the monitor or mixmonitor if the option is set
06286  * 7. Remove the caller from the queue to allow other callers to advance
06287  * 8. Bridge the call.
06288  * 9. Do any post processing after the call has disconnected.
06289  *
06290  * \param[in] qe the queue_ent structure which corresponds to the caller attempting to reach members
06291  * \param[in] opts the options passed as the third parameter to the Queue() application
06292  * \param[in] opt_args the options passed as the third parameter to the Queue() application
06293  * \param[in] announceoverride filename to play to user when waiting
06294  * \param[in] url the url passed as the fourth parameter to the Queue() application
06295  * \param[in,out] tries the number of times we have tried calling queue members
06296  * \param[out] noption set if the call to Queue() has the 'n' option set.
06297  * \param[in] agi the agi passed as the fifth parameter to the Queue() application
06298  * \param[in] macro the macro passed as the sixth parameter to the Queue() application
06299  * \param[in] gosub the gosub passed as the seventh parameter to the Queue() application
06300  * \param[in] ringing 1 if the 'r' option is set, otherwise 0
06301  */
06302 static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
06303 {
06304    struct member *cur;
06305    struct callattempt *outgoing = NULL; /* the list of calls we are building */
06306    int to, orig;
06307    char oldexten[AST_MAX_EXTENSION]="";
06308    char oldcontext[AST_MAX_CONTEXT]="";
06309    char queuename[256]="";
06310    char interfacevar[256]="";
06311    struct ast_channel *peer;
06312    struct ast_channel *which;
06313    struct callattempt *lpeer;
06314    struct member *member;
06315    struct ast_app *application;
06316    int res = 0, bridge = 0;
06317    int numbusies = 0;
06318    int x=0;
06319    char *announce = NULL;
06320    char digit = 0;
06321    time_t callstart;
06322    time_t now = time(NULL);
06323    struct ast_bridge_config bridge_config;
06324    char nondataquality = 1;
06325    char *agiexec = NULL;
06326    char *macroexec = NULL;
06327    char *gosubexec = NULL;