Sat Apr 26 2014 22:01:27

Asterisk developer's documentation


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  * \arg Config in \ref Config_qu queues.conf
00026  *
00027  * \par Development notes
00028  * \note 2004-11-25: Persistent Dynamic Members added by:
00029  *             NetNation Communications (www.netnation.com)
00030  *             Kevin Lindsay <kevinl@netnation.com>
00031  *
00032  *             Each dynamic agent in each queue is now stored in the astdb.
00033  *             When asterisk is restarted, each agent will be automatically
00034  *             readded into their recorded queues. This feature can be
00035  *             configured with the 'persistent_members=<1|0>' setting in the
00036  *             '[general]' category in queues.conf. The default is on.
00037  *
00038  * \note 2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
00039  *
00040  * \note These features added by David C. Troy <dave@toad.net>:
00041  *    - Per-queue holdtime calculation
00042  *    - Estimated holdtime announcement
00043  *    - Position announcement
00044  *    - Abandoned/completed call counters
00045  *    - Failout timer passed as optional app parameter
00046  *    - Optional monitoring of calls, started when call is answered
00047  *
00048  * Patch Version 1.07 2003-12-24 01
00049  *
00050  * Added servicelevel statistic by Michiel Betel <michiel@betel.nl>
00051  * Added Priority jumping code for adding and removing queue members by Jonathan Stanton <asterisk@doilooklikeicare.com>
00052  *
00053  * Fixed to work with CVS as of 2004-02-25 and released as 1.07a
00054  * by Matthew Enger <m.enger@xi.com.au>
00055  *
00056  * \ingroup applications
00057  */
00058 
00059 /*** MODULEINFO
00060    <use type="module">res_monitor</use>
00061    <support_level>core</support_level>
00062  ***/
00063 
00064 #include "asterisk.h"
00065 
00066 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409208 $")
00067 
00068 #include <sys/time.h>
00069 #include <sys/signal.h>
00070 #include <netinet/in.h>
00071 #include <ctype.h>
00072 
00073 #include "asterisk/lock.h"
00074 #include "asterisk/file.h"
00075 #include "asterisk/channel.h"
00076 #include "asterisk/pbx.h"
00077 #include "asterisk/app.h"
00078 #include "asterisk/linkedlists.h"
00079 #include "asterisk/module.h"
00080 #include "asterisk/translate.h"
00081 #include "asterisk/say.h"
00082 #include "asterisk/features.h"
00083 #include "asterisk/musiconhold.h"
00084 #include "asterisk/cli.h"
00085 #include "asterisk/manager.h"
00086 #include "asterisk/config.h"
00087 #include "asterisk/monitor.h"
00088 #include "asterisk/utils.h"
00089 #include "asterisk/causes.h"
00090 #include "asterisk/astdb.h"
00091 #include "asterisk/devicestate.h"
00092 #include "asterisk/stringfields.h"
00093 #include "asterisk/event.h"
00094 #include "asterisk/astobj2.h"
00095 #include "asterisk/strings.h"
00096 #include "asterisk/global_datastores.h"
00097 #include "asterisk/taskprocessor.h"
00098 #include "asterisk/aoc.h"
00099 #include "asterisk/callerid.h"
00100 #include "asterisk/cel.h"
00101 #include "asterisk/data.h"
00102 
00103 /* Define, to debug reference counts on queues, without debugging reference counts on queue members */
00104 /* #define REF_DEBUG_ONLY_QUEUES */
00105 
00106 /*!
00107  * \par Please read before modifying this file.
00108  * There are three locks which are regularly used
00109  * throughout this file, the queue list lock, the lock
00110  * for each individual queue, and the interface list lock.
00111  * Please be extra careful to always lock in the following order
00112  * 1) queue list lock
00113  * 2) individual queue lock
00114  * 3) interface list lock
00115  * This order has sort of "evolved" over the lifetime of this
00116  * application, but it is now in place this way, so please adhere
00117  * to this order!
00118  */
00119 
00120 /*** DOCUMENTATION
00121    <application name="Queue" language="en_US">
00122       <synopsis>
00123          Queue a call for a call queue.
00124       </synopsis>
00125       <syntax>
00126          <parameter name="queuename" required="true" />
00127          <parameter name="options">
00128             <optionlist>
00129                <option name="C">
00130                   <para>Mark all calls as "answered elsewhere" when cancelled.</para>
00131                </option>
00132                <option name="c">
00133                   <para>Continue in the dialplan if the callee hangs up.</para>
00134                </option>
00135                <option name="d">
00136                   <para>data-quality (modem) call (minimum delay).</para>
00137                </option>
00138                <option name="F" argsep="^">
00139                   <argument name="context" required="false" />
00140                   <argument name="exten" required="false" />
00141                   <argument name="priority" required="true" />
00142                   <para>When the caller hangs up, transfer the <emphasis>called member</emphasis>
00143                   to the specified destination and <emphasis>start</emphasis> execution at that location.</para>
00144                   <note>
00145                      <para>Any channel variables you want the called channel to inherit from the caller channel must be
00146                      prefixed with one or two underbars ('_').</para>
00147                   </note>
00148                </option>
00149                <option name="F">
00150                   <para>When the caller hangs up, transfer the <emphasis>called member</emphasis> to the next priority of
00151                   the current extension and <emphasis>start</emphasis> execution at that location.</para>
00152                   <note>
00153                      <para>Any channel variables you want the called channel to inherit from the caller channel must be
00154                      prefixed with one or two underbars ('_').</para>
00155                   </note>
00156                   <note>
00157                      <para>Using this option from a Macro() or GoSub() might not make sense as there would be no return points.</para>
00158                   </note>
00159                </option>
00160                <option name="h">
00161                   <para>Allow <emphasis>callee</emphasis> to hang up by pressing <literal>*</literal>.</para>
00162                </option>
00163                <option name="H">
00164                   <para>Allow <emphasis>caller</emphasis> to hang up by pressing <literal>*</literal>.</para>
00165                </option>
00166                <option name="n">
00167                   <para>No retries on the timeout; will exit this application and
00168                   go to the next step.</para>
00169                </option>
00170                <option name="i">
00171                   <para>Ignore call forward requests from queue members and do nothing
00172                   when they are requested.</para>
00173                </option>
00174                <option name="I">
00175                   <para>Asterisk will ignore any connected line update requests or any redirecting party
00176                   update requests it may receive on this dial attempt.</para>
00177                </option>
00178                <option name="r">
00179                   <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
00180                </option>
00181                <option name="R">
00182                   <para>Ring instead of playing MOH when a member channel is actually ringing.</para>
00183                </option>
00184                <option name="t">
00185                   <para>Allow the <emphasis>called</emphasis> user to transfer the calling user.</para>
00186                </option>
00187                <option name="T">
00188                   <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para>
00189                </option>
00190                <option name="w">
00191                   <para>Allow the <emphasis>called</emphasis> user to write the conversation to
00192                   disk via Monitor.</para>
00193                </option>
00194                <option name="W">
00195                   <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
00196                   disk via Monitor.</para>
00197                </option>
00198                <option name="k">
00199                   <para>Allow the <emphasis>called</emphasis> party to enable parking of the call by sending
00200                   the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
00201                </option>
00202                <option name="K">
00203                   <para>Allow the <emphasis>calling</emphasis> party to enable parking of the call by sending
00204                   the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
00205                </option>
00206                <option name="x">
00207                   <para>Allow the <emphasis>called</emphasis> user to write the conversation
00208                   to disk via MixMonitor.</para>
00209                </option>
00210                <option name="X">
00211                   <para>Allow the <emphasis>calling</emphasis> user to write the conversation to
00212                   disk via MixMonitor.</para>
00213                </option>
00214             </optionlist>
00215          </parameter>
00216          <parameter name="URL">
00217             <para><replaceable>URL</replaceable> will be sent to the called party if the channel supports it.</para>
00218          </parameter>
00219          <parameter name="announceoverride" />
00220          <parameter name="timeout">
00221             <para>Will cause the queue to fail out after a specified number of
00222             seconds, checked between each <filename>queues.conf</filename> <replaceable>timeout</replaceable> and
00223             <replaceable>retry</replaceable> cycle.</para>
00224          </parameter>
00225          <parameter name="AGI">
00226             <para>Will setup an AGI script to be executed on the calling party's channel once they are
00227             connected to a queue member.</para>
00228          </parameter>
00229          <parameter name="macro">
00230             <para>Will run a macro on the called party's channel (the queue member) once the parties are connected.</para>
00231          </parameter>
00232          <parameter name="gosub">
00233             <para>Will run a gosub on the called party's channel (the queue member) once the parties are connected.</para>
00234          </parameter>
00235          <parameter name="rule">
00236             <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
00237          </parameter>
00238          <parameter name="position">
00239             <para>Attempt to enter the caller into the queue at the numerical position specified. <literal>1</literal>
00240             would attempt to enter the caller at the head of the queue, and <literal>3</literal> would attempt to place
00241             the caller third in the queue.</para>
00242          </parameter>
00243       </syntax>
00244       <description>
00245          <para>In addition to transferring the call, a call may be parked and then picked
00246          up by another user.</para>
00247          <para>This application will return to the dialplan if the queue does not exist, or
00248          any of the join options cause the caller to not enter the queue.</para>
00249          <para>This application does not automatically answer and should be preceeded
00250          by an application such as Answer(), Progress(), or Ringing().</para>
00251          <para>This application sets the following channel variable upon completion:</para>
00252          <variablelist>
00253             <variable name="QUEUESTATUS">
00254                <para>The status of the call as a text string.</para>
00255                <value name="TIMEOUT" />
00256                <value name="FULL" />
00257                <value name="JOINEMPTY" />
00258                <value name="LEAVEEMPTY" />
00259                <value name="JOINUNAVAIL" />
00260                <value name="LEAVEUNAVAIL" />
00261                <value name="CONTINUE" />
00262             </variable>
00263          </variablelist>
00264       </description>
00265       <see-also>
00266          <ref type="application">Queue</ref>
00267          <ref type="application">QueueLog</ref>
00268          <ref type="application">AddQueueMember</ref>
00269          <ref type="application">RemoveQueueMember</ref>
00270          <ref type="application">PauseQueueMember</ref>
00271          <ref type="application">UnpauseQueueMember</ref>
00272          <ref type="function">QUEUE_VARIABLES</ref>
00273          <ref type="function">QUEUE_MEMBER</ref>
00274          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00275          <ref type="function">QUEUE_EXISTS</ref>
00276          <ref type="function">QUEUE_WAITING_COUNT</ref>
00277          <ref type="function">QUEUE_MEMBER_LIST</ref>
00278          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00279       </see-also>
00280    </application>
00281    <application name="AddQueueMember" language="en_US">
00282       <synopsis>
00283          Dynamically adds queue members.
00284       </synopsis>
00285       <syntax>
00286          <parameter name="queuename" required="true" />
00287          <parameter name="interface" />
00288          <parameter name="penalty" />
00289          <parameter name="options" />
00290          <parameter name="membername" />
00291          <parameter name="stateinterface" />
00292       </syntax>
00293       <description>
00294          <para>Dynamically adds interface to an existing queue. If the interface is
00295          already in the queue it will return an error.</para>
00296          <para>This application sets the following channel variable upon completion:</para>
00297          <variablelist>
00298             <variable name="AQMSTATUS">
00299                <para>The status of the attempt to add a queue member as a text string.</para>
00300                <value name="ADDED" />
00301                <value name="MEMBERALREADY" />
00302                <value name="NOSUCHQUEUE" />
00303             </variable>
00304          </variablelist>
00305       </description>
00306       <see-also>
00307          <ref type="application">Queue</ref>
00308          <ref type="application">QueueLog</ref>
00309          <ref type="application">AddQueueMember</ref>
00310          <ref type="application">RemoveQueueMember</ref>
00311          <ref type="application">PauseQueueMember</ref>
00312          <ref type="application">UnpauseQueueMember</ref>
00313          <ref type="function">QUEUE_VARIABLES</ref>
00314          <ref type="function">QUEUE_MEMBER</ref>
00315          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00316          <ref type="function">QUEUE_EXISTS</ref>
00317          <ref type="function">QUEUE_WAITING_COUNT</ref>
00318          <ref type="function">QUEUE_MEMBER_LIST</ref>
00319          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00320       </see-also>
00321    </application>
00322    <application name="RemoveQueueMember" language="en_US">
00323       <synopsis>
00324          Dynamically removes queue members.
00325       </synopsis>
00326       <syntax>
00327          <parameter name="queuename" required="true" />
00328          <parameter name="interface" />
00329       </syntax>
00330       <description>
00331          <para>If the interface is <emphasis>NOT</emphasis> in the queue it will return an error.</para>
00332          <para>This application sets the following channel variable upon completion:</para>
00333          <variablelist>
00334             <variable name="RQMSTATUS">
00335                <value name="REMOVED" />
00336                <value name="NOTINQUEUE" />
00337                <value name="NOSUCHQUEUE" />
00338                <value name="NOTDYNAMIC" />
00339             </variable>
00340          </variablelist>
00341          <para>Example: RemoveQueueMember(techsupport,SIP/3000)</para>
00342       </description>
00343       <see-also>
00344          <ref type="application">Queue</ref>
00345          <ref type="application">QueueLog</ref>
00346          <ref type="application">AddQueueMember</ref>
00347          <ref type="application">RemoveQueueMember</ref>
00348          <ref type="application">PauseQueueMember</ref>
00349          <ref type="application">UnpauseQueueMember</ref>
00350          <ref type="function">QUEUE_VARIABLES</ref>
00351          <ref type="function">QUEUE_MEMBER</ref>
00352          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00353          <ref type="function">QUEUE_EXISTS</ref>
00354          <ref type="function">QUEUE_WAITING_COUNT</ref>
00355          <ref type="function">QUEUE_MEMBER_LIST</ref>
00356          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00357       </see-also>
00358    </application>
00359    <application name="PauseQueueMember" language="en_US">
00360       <synopsis>
00361          Pauses a queue member.
00362       </synopsis>
00363       <syntax>
00364          <parameter name="queuename" />
00365          <parameter name="interface" required="true" />
00366          <parameter name="options" />
00367          <parameter name="reason">
00368             <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
00369          </parameter>
00370       </syntax>
00371       <description>
00372          <para>Pauses (blocks calls for) a queue member. The given interface will be paused in the given queue.
00373          This prevents any calls from being sent from the queue to the interface until it is
00374          unpaused with UnpauseQueueMember or the manager interface.  If no queuename is given,
00375          the interface is paused in every queue it is a member of. The application will fail if the
00376          interface is not found.</para>
00377          <para>This application sets the following channel variable upon completion:</para>
00378          <variablelist>
00379             <variable name="PQMSTATUS">
00380                <para>The status of the attempt to pause a queue member as a text string.</para>
00381                <value name="PAUSED" />
00382                <value name="NOTFOUND" />
00383             </variable>
00384          </variablelist>
00385          <para>Example: PauseQueueMember(,SIP/3000)</para>
00386       </description>
00387       <see-also>
00388          <ref type="application">Queue</ref>
00389          <ref type="application">QueueLog</ref>
00390          <ref type="application">AddQueueMember</ref>
00391          <ref type="application">RemoveQueueMember</ref>
00392          <ref type="application">PauseQueueMember</ref>
00393          <ref type="application">UnpauseQueueMember</ref>
00394          <ref type="function">QUEUE_VARIABLES</ref>
00395          <ref type="function">QUEUE_MEMBER</ref>
00396          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00397          <ref type="function">QUEUE_EXISTS</ref>
00398          <ref type="function">QUEUE_WAITING_COUNT</ref>
00399          <ref type="function">QUEUE_MEMBER_LIST</ref>
00400          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00401       </see-also>
00402    </application>
00403    <application name="UnpauseQueueMember" language="en_US">
00404       <synopsis>
00405          Unpauses a queue member.
00406       </synopsis>
00407       <syntax>
00408          <parameter name="queuename" />
00409          <parameter name="interface" required="true" />
00410          <parameter name="options" />
00411          <parameter name="reason">
00412             <para>Is used to add extra information to the appropriate queue_log entries and manager events.</para>
00413          </parameter>
00414       </syntax>
00415       <description>
00416          <para>Unpauses (resumes calls to) a queue member. This is the counterpart to <literal>PauseQueueMember()</literal>
00417          and operates exactly the same way, except it unpauses instead of pausing the given interface.</para>
00418          <para>This application sets the following channel variable upon completion:</para>
00419          <variablelist>
00420             <variable name="UPQMSTATUS">
00421                <para>The status of the attempt to unpause a queue member as a text string.</para>
00422                <value name="UNPAUSED" />
00423                <value name="NOTFOUND" />
00424             </variable>
00425          </variablelist>
00426          <para>Example: UnpauseQueueMember(,SIP/3000)</para>
00427       </description>
00428       <see-also>
00429          <ref type="application">Queue</ref>
00430          <ref type="application">QueueLog</ref>
00431          <ref type="application">AddQueueMember</ref>
00432          <ref type="application">RemoveQueueMember</ref>
00433          <ref type="application">PauseQueueMember</ref>
00434          <ref type="application">UnpauseQueueMember</ref>
00435          <ref type="function">QUEUE_VARIABLES</ref>
00436          <ref type="function">QUEUE_MEMBER</ref>
00437          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00438          <ref type="function">QUEUE_EXISTS</ref>
00439          <ref type="function">QUEUE_WAITING_COUNT</ref>
00440          <ref type="function">QUEUE_MEMBER_LIST</ref>
00441          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00442       </see-also>
00443    </application>
00444    <application name="QueueLog" language="en_US">
00445       <synopsis>
00446          Writes to the queue_log file.
00447       </synopsis>
00448       <syntax>
00449          <parameter name="queuename" required="true" />
00450          <parameter name="uniqueid" required="true" />
00451          <parameter name="agent" required="true" />
00452          <parameter name="event" required="true" />
00453          <parameter name="additionalinfo" />
00454       </syntax>
00455       <description>
00456          <para>Allows you to write your own events into the queue log.</para>
00457          <para>Example: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)</para>
00458       </description>
00459       <see-also>
00460          <ref type="application">Queue</ref>
00461          <ref type="application">QueueLog</ref>
00462          <ref type="application">AddQueueMember</ref>
00463          <ref type="application">RemoveQueueMember</ref>
00464          <ref type="application">PauseQueueMember</ref>
00465          <ref type="application">UnpauseQueueMember</ref>
00466          <ref type="function">QUEUE_VARIABLES</ref>
00467          <ref type="function">QUEUE_MEMBER</ref>
00468          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00469          <ref type="function">QUEUE_EXISTS</ref>
00470          <ref type="function">QUEUE_WAITING_COUNT</ref>
00471          <ref type="function">QUEUE_MEMBER_LIST</ref>
00472          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00473       </see-also>
00474    </application>
00475    <function name="QUEUE_VARIABLES" language="en_US">
00476       <synopsis>
00477          Return Queue information in variables.
00478       </synopsis>
00479       <syntax>
00480          <parameter name="queuename" required="true">
00481             <enumlist>
00482                <enum name="QUEUEMAX">
00483                   <para>Maxmimum number of calls allowed.</para>
00484                </enum>
00485                <enum name="QUEUESTRATEGY">
00486                   <para>The strategy of the queue.</para>
00487                </enum>
00488                <enum name="QUEUECALLS">
00489                   <para>Number of calls currently in the queue.</para>
00490                </enum>
00491                <enum name="QUEUEHOLDTIME">
00492                   <para>Current average hold time.</para>
00493                </enum>
00494                <enum name="QUEUECOMPLETED">
00495                   <para>Number of completed calls for the queue.</para>
00496                </enum>
00497                <enum name="QUEUEABANDONED">
00498                   <para>Number of abandoned calls.</para>
00499                </enum>
00500                <enum name="QUEUESRVLEVEL">
00501                   <para>Queue service level.</para>
00502                </enum>
00503                <enum name="QUEUESRVLEVELPERF">
00504                   <para>Current service level performance.</para>
00505                </enum>
00506             </enumlist>
00507          </parameter>
00508       </syntax>
00509       <description>
00510          <para>Makes the following queue variables available.</para>
00511          <para>Returns <literal>0</literal> if queue is found and setqueuevar is defined, <literal>-1</literal> otherwise.</para>
00512       </description>
00513       <see-also>
00514          <ref type="application">Queue</ref>
00515          <ref type="application">QueueLog</ref>
00516          <ref type="application">AddQueueMember</ref>
00517          <ref type="application">RemoveQueueMember</ref>
00518          <ref type="application">PauseQueueMember</ref>
00519          <ref type="application">UnpauseQueueMember</ref>
00520          <ref type="function">QUEUE_VARIABLES</ref>
00521          <ref type="function">QUEUE_MEMBER</ref>
00522          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00523          <ref type="function">QUEUE_EXISTS</ref>
00524          <ref type="function">QUEUE_WAITING_COUNT</ref>
00525          <ref type="function">QUEUE_MEMBER_LIST</ref>
00526          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00527       </see-also>
00528    </function>
00529    <function name="QUEUE_MEMBER" language="en_US">
00530       <synopsis>
00531          Count number of members answering a queue.
00532       </synopsis>
00533       <syntax>
00534          <parameter name="queuename" required="true" />
00535          <parameter name="option" required="true">
00536             <enumlist>
00537                <enum name="logged">
00538                   <para>Returns the number of logged-in members for the specified queue.</para>
00539                </enum>
00540                <enum name="free">
00541                   <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>
00542                </enum>
00543                <enum name="ready">
00544                   <para>Returns the number of logged-in members for the specified queue that are immediately available to answer a call.</para>
00545                </enum>
00546                <enum name="count">
00547                   <para>Returns the total number of members for the specified queue.</para>
00548                </enum>
00549                <enum name="penalty">
00550                   <para>Gets or sets queue member penalty.</para>
00551                </enum>
00552                <enum name="paused">
00553                   <para>Gets or sets queue member paused status.</para>
00554                </enum>
00555                <enum name="ringinuse">
00556                   <para>Gets or sets queue member ringinuse.</para>
00557                </enum>
00558             </enumlist>
00559          </parameter>
00560          <parameter name="interface" required="false" />
00561       </syntax>
00562       <description>
00563          <para>Allows access to queue counts [R] and member information [R/W].</para>
00564          <para>
00565             <replaceable>queuename</replaceable> is required for all operations
00566             <replaceable>interface</replaceable> is required for all member operations.
00567          </para>
00568       </description>
00569       <see-also>
00570          <ref type="application">Queue</ref>
00571          <ref type="application">QueueLog</ref>
00572          <ref type="application">AddQueueMember</ref>
00573          <ref type="application">RemoveQueueMember</ref>
00574          <ref type="application">PauseQueueMember</ref>
00575          <ref type="application">UnpauseQueueMember</ref>
00576          <ref type="function">QUEUE_VARIABLES</ref>
00577          <ref type="function">QUEUE_MEMBER</ref>
00578          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00579          <ref type="function">QUEUE_EXISTS</ref>
00580          <ref type="function">QUEUE_WAITING_COUNT</ref>
00581          <ref type="function">QUEUE_MEMBER_LIST</ref>
00582          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00583       </see-also>
00584    </function>
00585    <function name="QUEUE_MEMBER_COUNT" language="en_US">
00586       <synopsis>
00587          Count number of members answering a queue.
00588       </synopsis>
00589       <syntax>
00590          <parameter name="queuename" required="true" />
00591       </syntax>
00592       <description>
00593          <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
00594          <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
00595       </description>
00596       <see-also>
00597          <ref type="application">Queue</ref>
00598          <ref type="application">QueueLog</ref>
00599          <ref type="application">AddQueueMember</ref>
00600          <ref type="application">RemoveQueueMember</ref>
00601          <ref type="application">PauseQueueMember</ref>
00602          <ref type="application">UnpauseQueueMember</ref>
00603          <ref type="function">QUEUE_VARIABLES</ref>
00604          <ref type="function">QUEUE_MEMBER</ref>
00605          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00606          <ref type="function">QUEUE_EXISTS</ref>
00607          <ref type="function">QUEUE_WAITING_COUNT</ref>
00608          <ref type="function">QUEUE_MEMBER_LIST</ref>
00609          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00610       </see-also>
00611    </function>
00612    <function name="QUEUE_EXISTS" language="en_US">
00613       <synopsis>
00614          Check if a named queue exists on this server
00615       </synopsis>
00616       <syntax>
00617          <parameter name="queuename" />
00618       </syntax>
00619       <description>
00620          <para>Returns 1 if the specified queue exists, 0 if it does not</para>
00621       </description>
00622       <see-also>
00623          <ref type="application">Queue</ref>
00624          <ref type="application">QueueLog</ref>
00625          <ref type="application">AddQueueMember</ref>
00626          <ref type="application">RemoveQueueMember</ref>
00627          <ref type="application">PauseQueueMember</ref>
00628          <ref type="application">UnpauseQueueMember</ref>
00629          <ref type="function">QUEUE_VARIABLES</ref>
00630          <ref type="function">QUEUE_MEMBER</ref>
00631          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00632          <ref type="function">QUEUE_EXISTS</ref>
00633          <ref type="function">QUEUE_WAITING_COUNT</ref>
00634          <ref type="function">QUEUE_MEMBER_LIST</ref>
00635          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00636       </see-also>
00637    </function>
00638    <function name="QUEUE_WAITING_COUNT" language="en_US">
00639       <synopsis>
00640          Count number of calls currently waiting in a queue.
00641       </synopsis>
00642       <syntax>
00643          <parameter name="queuename" />
00644       </syntax>
00645       <description>
00646          <para>Returns the number of callers currently waiting in the specified <replaceable>queuename</replaceable>.</para>
00647       </description>
00648       <see-also>
00649          <ref type="application">Queue</ref>
00650          <ref type="application">QueueLog</ref>
00651          <ref type="application">AddQueueMember</ref>
00652          <ref type="application">RemoveQueueMember</ref>
00653          <ref type="application">PauseQueueMember</ref>
00654          <ref type="application">UnpauseQueueMember</ref>
00655          <ref type="function">QUEUE_VARIABLES</ref>
00656          <ref type="function">QUEUE_MEMBER</ref>
00657          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00658          <ref type="function">QUEUE_EXISTS</ref>
00659          <ref type="function">QUEUE_WAITING_COUNT</ref>
00660          <ref type="function">QUEUE_MEMBER_LIST</ref>
00661          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00662       </see-also>
00663    </function>
00664    <function name="QUEUE_MEMBER_LIST" language="en_US">
00665       <synopsis>
00666          Returns a list of interfaces on a queue.
00667       </synopsis>
00668       <syntax>
00669          <parameter name="queuename" required="true" />
00670       </syntax>
00671       <description>
00672          <para>Returns a comma-separated list of members associated with the specified <replaceable>queuename</replaceable>.</para>
00673       </description>
00674       <see-also>
00675          <ref type="application">Queue</ref>
00676          <ref type="application">QueueLog</ref>
00677          <ref type="application">AddQueueMember</ref>
00678          <ref type="application">RemoveQueueMember</ref>
00679          <ref type="application">PauseQueueMember</ref>
00680          <ref type="application">UnpauseQueueMember</ref>
00681          <ref type="function">QUEUE_VARIABLES</ref>
00682          <ref type="function">QUEUE_MEMBER</ref>
00683          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00684          <ref type="function">QUEUE_EXISTS</ref>
00685          <ref type="function">QUEUE_WAITING_COUNT</ref>
00686          <ref type="function">QUEUE_MEMBER_LIST</ref>
00687          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00688       </see-also>
00689    </function>
00690    <function name="QUEUE_MEMBER_PENALTY" language="en_US">
00691       <synopsis>
00692          Gets or sets queue members penalty.
00693       </synopsis>
00694       <syntax>
00695          <parameter name="queuename" required="true" />
00696          <parameter name="interface" required="true" />
00697       </syntax>
00698       <description>
00699          <para>Gets or sets queue members penalty.</para>
00700          <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
00701       </description>
00702       <see-also>
00703          <ref type="application">Queue</ref>
00704          <ref type="application">QueueLog</ref>
00705          <ref type="application">AddQueueMember</ref>
00706          <ref type="application">RemoveQueueMember</ref>
00707          <ref type="application">PauseQueueMember</ref>
00708          <ref type="application">UnpauseQueueMember</ref>
00709          <ref type="function">QUEUE_VARIABLES</ref>
00710          <ref type="function">QUEUE_MEMBER</ref>
00711          <ref type="function">QUEUE_MEMBER_COUNT</ref>
00712          <ref type="function">QUEUE_EXISTS</ref>
00713          <ref type="function">QUEUE_WAITING_COUNT</ref>
00714          <ref type="function">QUEUE_MEMBER_LIST</ref>
00715          <ref type="function">QUEUE_MEMBER_PENALTY</ref>
00716       </see-also>
00717    </function>
00718    <manager name="Queues" language="en_US">
00719       <synopsis>
00720          Queues.
00721       </synopsis>
00722       <syntax>
00723       </syntax>
00724       <description>
00725       </description>
00726    </manager>
00727    <manager name="QueueStatus" language="en_US">
00728       <synopsis>
00729          Show queue status.
00730       </synopsis>
00731       <syntax>
00732          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00733          <parameter name="Queue" />
00734          <parameter name="Member" />
00735       </syntax>
00736       <description>
00737       </description>
00738    </manager>
00739    <manager name="QueueSummary" language="en_US">
00740       <synopsis>
00741          Show queue summary.
00742       </synopsis>
00743       <syntax>
00744          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00745          <parameter name="Queue" />
00746       </syntax>
00747       <description>
00748       </description>
00749    </manager>
00750    <manager name="QueueAdd" language="en_US">
00751       <synopsis>
00752          Add interface to queue.
00753       </synopsis>
00754       <syntax>
00755          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00756          <parameter name="Queue" required="true" />
00757          <parameter name="Interface" required="true" />
00758          <parameter name="Penalty" />
00759          <parameter name="Paused" />
00760          <parameter name="MemberName" />
00761          <parameter name="StateInterface" />
00762       </syntax>
00763       <description>
00764       </description>
00765    </manager>
00766    <manager name="QueueRemove" language="en_US">
00767       <synopsis>
00768          Remove interface from queue.
00769       </synopsis>
00770       <syntax>
00771          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00772          <parameter name="Queue" required="true" />
00773          <parameter name="Interface" required="true" />
00774       </syntax>
00775       <description>
00776       </description>
00777    </manager>
00778    <manager name="QueuePause" language="en_US">
00779       <synopsis>
00780          Makes a queue member temporarily unavailable.
00781       </synopsis>
00782       <syntax>
00783          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00784          <parameter name="Interface" required="true" />
00785          <parameter name="Paused" required="true" />
00786          <parameter name="Queue" />
00787          <parameter name="Reason" />
00788       </syntax>
00789       <description>
00790       </description>
00791    </manager>
00792    <manager name="QueueLog" language="en_US">
00793       <synopsis>
00794          Adds custom entry in queue_log.
00795       </synopsis>
00796       <syntax>
00797          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00798          <parameter name="Queue" required="true" />
00799          <parameter name="Event" required="true" />
00800          <parameter name="Uniqueid" />
00801          <parameter name="Interface" />
00802          <parameter name="Message" />
00803       </syntax>
00804       <description>
00805       </description>
00806    </manager>
00807    <manager name="QueuePenalty" language="en_US">
00808       <synopsis>
00809          Set the penalty for a queue member.
00810       </synopsis>
00811       <syntax>
00812          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00813          <parameter name="Interface" required="true" />
00814          <parameter name="Penalty" required="true" />
00815          <parameter name="Queue" />
00816       </syntax>
00817       <description>
00818       </description>
00819    </manager>
00820 
00821    <manager name="QueueMemberRingInUse" language="en_US">
00822       <synopsis>
00823          Set the ringinuse value for a queue member.
00824       </synopsis>
00825       <syntax>
00826          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00827          <parameter name="Interface" required="true" />
00828          <parameter name="RingInUse" required="true" />
00829          <parameter name="Queue" />
00830       </syntax>
00831       <description>
00832       </description>
00833    </manager>
00834 
00835    <manager name="QueueRule" language="en_US">
00836       <synopsis>
00837          Queue Rules.
00838       </synopsis>
00839       <syntax>
00840          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00841          <parameter name="Rule" />
00842       </syntax>
00843       <description>
00844       </description>
00845    </manager>
00846    <manager name="QueueReload" language="en_US">
00847       <synopsis>
00848          Reload a queue, queues, or any sub-section of a queue or queues.
00849       </synopsis>
00850       <syntax>
00851          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00852          <parameter name="Queue" />
00853          <parameter name="Members">
00854             <enumlist>
00855                <enum name="yes" />
00856                <enum name="no" />
00857             </enumlist>
00858          </parameter>
00859          <parameter name="Rules">
00860             <enumlist>
00861                <enum name="yes" />
00862                <enum name="no" />
00863             </enumlist>
00864          </parameter>
00865          <parameter name="Parameters">
00866             <enumlist>
00867                <enum name="yes" />
00868                <enum name="no" />
00869             </enumlist>
00870          </parameter>
00871       </syntax>
00872       <description>
00873       </description>
00874    </manager>
00875    <manager name="QueueReset" language="en_US">
00876       <synopsis>
00877          Reset queue statistics.
00878       </synopsis>
00879       <syntax>
00880          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00881          <parameter name="Queue" />
00882       </syntax>
00883       <description>
00884       </description>
00885    </manager>
00886  ***/
00887 
00888 enum {
00889    OPT_MARK_AS_ANSWERED =       (1 << 0),
00890    OPT_GO_ON =                  (1 << 1),
00891    OPT_DATA_QUALITY =           (1 << 2),
00892    OPT_CALLEE_GO_ON =           (1 << 3),
00893    OPT_CALLEE_HANGUP =          (1 << 4),
00894    OPT_CALLER_HANGUP =          (1 << 5),
00895    OPT_IGNORE_CALL_FW =         (1 << 6),
00896    OPT_IGNORE_CONNECTEDLINE =   (1 << 7),
00897    OPT_CALLEE_PARK =            (1 << 8),
00898    OPT_CALLER_PARK =            (1 << 9),
00899    OPT_NO_RETRY =               (1 << 10),
00900    OPT_RINGING =                (1 << 11),
00901    OPT_RING_WHEN_RINGING =      (1 << 12),
00902    OPT_CALLEE_TRANSFER =        (1 << 13),
00903    OPT_CALLER_TRANSFER =        (1 << 14),
00904    OPT_CALLEE_AUTOMIXMON =      (1 << 15),
00905    OPT_CALLER_AUTOMIXMON =      (1 << 16),
00906    OPT_CALLEE_AUTOMON =         (1 << 17),
00907    OPT_CALLER_AUTOMON =         (1 << 18),
00908 };
00909 
00910 enum {
00911    OPT_ARG_CALLEE_GO_ON = 0,
00912    /* note: this entry _MUST_ be the last one in the enum */
00913    OPT_ARG_ARRAY_SIZE
00914 };
00915 
00916 AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS
00917    AST_APP_OPTION('C', OPT_MARK_AS_ANSWERED),
00918    AST_APP_OPTION('c', OPT_GO_ON),
00919    AST_APP_OPTION('d', OPT_DATA_QUALITY),
00920    AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
00921    AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
00922    AST_APP_OPTION('H', OPT_CALLER_HANGUP),
00923    AST_APP_OPTION('i', OPT_IGNORE_CALL_FW),
00924    AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
00925    AST_APP_OPTION('k', OPT_CALLEE_PARK),
00926    AST_APP_OPTION('K', OPT_CALLER_PARK),
00927    AST_APP_OPTION('n', OPT_NO_RETRY),
00928    AST_APP_OPTION('r', OPT_RINGING),
00929    AST_APP_OPTION('R', OPT_RING_WHEN_RINGING),
00930    AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
00931    AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
00932    AST_APP_OPTION('x', OPT_CALLEE_AUTOMIXMON),
00933    AST_APP_OPTION('X', OPT_CALLER_AUTOMIXMON),
00934    AST_APP_OPTION('w', OPT_CALLEE_AUTOMON),
00935    AST_APP_OPTION('W', OPT_CALLER_AUTOMON),
00936 END_OPTIONS);
00937 
00938 enum {
00939    QUEUE_STRATEGY_RINGALL = 0,
00940    QUEUE_STRATEGY_LEASTRECENT,
00941    QUEUE_STRATEGY_FEWESTCALLS,
00942    QUEUE_STRATEGY_RANDOM,
00943    QUEUE_STRATEGY_RRMEMORY,
00944    QUEUE_STRATEGY_LINEAR,
00945    QUEUE_STRATEGY_WRANDOM,
00946    QUEUE_STRATEGY_RRORDERED,
00947 };
00948 
00949 enum {
00950      QUEUE_AUTOPAUSE_OFF = 0,
00951      QUEUE_AUTOPAUSE_ON,
00952      QUEUE_AUTOPAUSE_ALL
00953 };
00954 
00955 enum queue_reload_mask {
00956    QUEUE_RELOAD_PARAMETERS = (1 << 0),
00957    QUEUE_RELOAD_MEMBER = (1 << 1),
00958    QUEUE_RELOAD_RULES = (1 << 2),
00959    QUEUE_RESET_STATS = (1 << 3),
00960 };
00961 
00962 static const struct strategy {
00963    int strategy;
00964    const char *name;
00965 } strategies[] = {
00966    { QUEUE_STRATEGY_RINGALL, "ringall" },
00967    { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
00968    { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
00969    { QUEUE_STRATEGY_RANDOM, "random" },
00970    { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
00971    { QUEUE_STRATEGY_RRMEMORY, "roundrobin" },
00972    { QUEUE_STRATEGY_LINEAR, "linear" },
00973    { QUEUE_STRATEGY_WRANDOM, "wrandom"},
00974    { QUEUE_STRATEGY_RRORDERED, "rrordered"},
00975 };
00976 
00977 static const struct autopause {
00978    int autopause;
00979    const char *name;
00980 } autopausesmodes [] = {
00981    { QUEUE_AUTOPAUSE_OFF,"no" },
00982    { QUEUE_AUTOPAUSE_ON, "yes" },
00983    { QUEUE_AUTOPAUSE_ALL,"all" },
00984 };
00985 
00986 
00987 static struct ast_taskprocessor *devicestate_tps;
00988 
00989 #define DEFAULT_RETRY      5
00990 #define DEFAULT_TIMEOUT    15
00991 #define RECHECK         1     /*!< Recheck every second to see we we're at the top yet */
00992 #define MAX_PERIODIC_ANNOUNCEMENTS 10           /*!< The maximum periodic announcements we can have */
00993 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15       /*!< The minimum number of seconds between position announcements \
00994                                                      The default value of 15 provides backwards compatibility */
00995 #define MAX_QUEUE_BUCKETS 53
00996 
00997 #define  RES_OKAY 0     /*!< Action completed */
00998 #define  RES_EXISTS  (-1)     /*!< Entry already exists */
00999 #define  RES_OUTOFMEMORY   (-2)     /*!< Out of memory */
01000 #define  RES_NOSUCHQUEUE   (-3)     /*!< No such queue */
01001 #define RES_NOT_DYNAMIC (-4)     /*!< Member is not dynamic */
01002 
01003 static char *app = "Queue";
01004 
01005 static char *app_aqm = "AddQueueMember" ;
01006 
01007 static char *app_rqm = "RemoveQueueMember" ;
01008 
01009 static char *app_pqm = "PauseQueueMember" ;
01010 
01011 static char *app_upqm = "UnpauseQueueMember" ;
01012 
01013 static char *app_ql = "QueueLog" ;
01014 
01015 /*! \brief Persistent Members astdb family */
01016 static const char * const pm_family = "Queue/PersistentMembers";
01017 
01018 /*! \brief queues.conf [general] option */
01019 static int queue_persistent_members = 0;
01020 
01021 /*! \brief queues.conf per-queue weight option */
01022 static int use_weight = 0;
01023 
01024 /*! \brief queues.conf [general] option */
01025 static int autofill_default = 1;
01026 
01027 /*! \brief queues.conf [general] option */
01028 static int montype_default = 0;
01029 
01030 /*! \brief queues.conf [general] option */
01031 static int shared_lastcall = 1;
01032 
01033 /*! \brief Subscription to device state change events */
01034 static struct ast_event_sub *device_state_sub;
01035 
01036 /*! \brief queues.conf [general] option */
01037 static int update_cdr = 0;
01038 
01039 /*! \brief queues.conf [general] option */
01040 static int negative_penalty_invalid = 0;
01041 
01042 /*! \brief queues.conf [general] option */
01043 static int log_membername_as_agent = 0;
01044 
01045 /*! \brief name of the ringinuse field in the realtime database */
01046 static char *realtime_ringinuse_field;
01047 
01048 enum queue_result {
01049    QUEUE_UNKNOWN = 0,
01050    QUEUE_TIMEOUT = 1,
01051    QUEUE_JOINEMPTY = 2,
01052    QUEUE_LEAVEEMPTY = 3,
01053    QUEUE_JOINUNAVAIL = 4,
01054    QUEUE_LEAVEUNAVAIL = 5,
01055    QUEUE_FULL = 6,
01056    QUEUE_CONTINUE = 7,
01057 };
01058 
01059 static const struct {
01060    enum queue_result id;
01061    char *text;
01062 } queue_results[] = {
01063    { QUEUE_UNKNOWN, "UNKNOWN" },
01064    { QUEUE_TIMEOUT, "TIMEOUT" },
01065    { QUEUE_JOINEMPTY,"JOINEMPTY" },
01066    { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
01067    { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
01068    { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
01069    { QUEUE_FULL, "FULL" },
01070    { QUEUE_CONTINUE, "CONTINUE" },
01071 };
01072 
01073 enum queue_timeout_priority {
01074    TIMEOUT_PRIORITY_APP,
01075    TIMEOUT_PRIORITY_CONF,
01076 };
01077 
01078 /*! \brief We define a custom "local user" structure because we
01079  *  use it not only for keeping track of what is in use but
01080  *  also for keeping track of who we're dialing.
01081  *
01082  *  There are two "links" defined in this structure, q_next and call_next.
01083  *  q_next links ALL defined callattempt structures into a linked list. call_next is
01084  *  a link which allows for a subset of the callattempts to be traversed. This subset
01085  *  is used in wait_for_answer so that irrelevant callattempts are not traversed. This
01086  *  also is helpful so that queue logs are always accurate in the case where a call to
01087  *  a member times out, especially if using the ringall strategy.
01088 */
01089 
01090 struct callattempt {
01091    struct callattempt *q_next;
01092    struct callattempt *call_next;
01093    struct ast_channel *chan;
01094    char interface[256];       /*!< An Asterisk dial string (not a channel name) */
01095    int metric;
01096    time_t lastcall;
01097    struct call_queue *lastqueue;
01098    struct member *member;
01099    /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
01100    struct ast_party_connected_line connected;
01101    /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
01102    unsigned int pending_connected_update:1;
01103    /*! TRUE if the connected line update is blocked. */
01104    unsigned int block_connected_update:1;
01105    /*! TRUE if caller id is not available for connected line */
01106    unsigned int dial_callerid_absent:1;
01107    /*! TRUE if the call is still active */
01108    unsigned int stillgoing:1;
01109    struct ast_aoc_decoded *aoc_s_rate_list;
01110 };
01111 
01112 
01113 struct queue_ent {
01114    struct call_queue *parent;             /*!< What queue is our parent */
01115    char moh[MAX_MUSICCLASS];              /*!< Name of musiconhold to be used */
01116    char announce[PATH_MAX];               /*!< Announcement to play for member when call is answered */
01117    char context[AST_MAX_CONTEXT];         /*!< Context when user exits queue */
01118    char digits[AST_MAX_EXTENSION];        /*!< Digits entered while in queue */
01119    int valid_digits;                      /*!< Digits entered correspond to valid extension. Exited */
01120    int pos;                               /*!< Where we are in the queue */
01121    int prio;                              /*!< Our priority */
01122    int last_pos_said;                     /*!< Last position we told the user */
01123    int ring_when_ringing;                 /*!< Should we only use ring indication when a channel is ringing? */
01124    time_t last_periodic_announce_time;    /*!< The last time we played a periodic announcement */
01125    int last_periodic_announce_sound;      /*!< The last periodic announcement we made */
01126    time_t last_pos;                       /*!< Last time we told the user their position */
01127    int opos;                              /*!< Where we started in the queue */
01128    int handled;                           /*!< Whether our call was handled */
01129    int pending;                           /*!< Non-zero if we are attempting to call a member */
01130    int max_penalty;                       /*!< Limit the members that can take this call to this penalty or lower */
01131    int min_penalty;                       /*!< Limit the members that can take this call to this penalty or higher */
01132    int linpos;                            /*!< If using linear strategy, what position are we at? */
01133    int linwrapped;                        /*!< Is the linpos wrapped? */
01134    time_t start;                          /*!< When we started holding */
01135    time_t expire;                         /*!< When this entry should expire (time out of queue) */
01136    int cancel_answered_elsewhere;          /*!< Whether we should force the CAE flag on this call (C) option*/
01137    struct ast_channel *chan;              /*!< Our channel */
01138    AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules; /*!< Local copy of the queue's penalty rules */
01139    struct penalty_rule *pr;               /*!< Pointer to the next penalty rule to implement */
01140    struct queue_ent *next;                /*!< The next queue entry */
01141 };
01142 
01143 struct member {
01144    char interface[AST_CHANNEL_NAME];    /*!< Technology/Location to dial to reach this member*/
01145    char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */
01146    char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */
01147    char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */
01148    char membername[80];                 /*!< Member name to use in queue logs */
01149    int penalty;                         /*!< Are we a last resort? */
01150    int calls;                           /*!< Number of calls serviced by this member */
01151    int dynamic;                         /*!< Are we dynamically added? */
01152    int realtime;                        /*!< Is this member realtime? */
01153    int status;                          /*!< Status of queue member */
01154    int paused;                          /*!< Are we paused (not accepting calls)? */
01155    int queuepos;                        /*!< In what order (pertains to certain strategies) should this member be called? */
01156    time_t lastcall;                     /*!< When last successful call was hungup */
01157    struct call_queue *lastqueue;      /*!< Last queue we received a call */
01158    unsigned int dead:1;                 /*!< Used to detect members deleted in realtime */
01159    unsigned int delme:1;                /*!< Flag to delete entry on reload */
01160    unsigned int call_pending:1;         /*!< TRUE if the Q is attempting to place a call to the member. */
01161    char rt_uniqueid[80];                /*!< Unique id of realtime member entry */
01162    unsigned int ringinuse:1;            /*!< Flag to ring queue members even if their status is 'inuse' */
01163 };
01164 
01165 enum empty_conditions {
01166    QUEUE_EMPTY_PENALTY = (1 << 0),
01167    QUEUE_EMPTY_PAUSED = (1 << 1),
01168    QUEUE_EMPTY_INUSE = (1 << 2),
01169    QUEUE_EMPTY_RINGING = (1 << 3),
01170    QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
01171    QUEUE_EMPTY_INVALID = (1 << 5),
01172    QUEUE_EMPTY_UNKNOWN = (1 << 6),
01173    QUEUE_EMPTY_WRAPUP = (1 << 7),
01174 };
01175 
01176 enum member_properties {
01177    MEMBER_PENALTY = 0,
01178    MEMBER_RINGINUSE = 1,
01179 };
01180 
01181 /* values used in multi-bit flags in call_queue */
01182 #define ANNOUNCEHOLDTIME_ALWAYS 1
01183 #define ANNOUNCEHOLDTIME_ONCE 2
01184 #define QUEUE_EVENT_VARIABLES 3
01185 
01186 struct penalty_rule {
01187    int time;                           /*!< Number of seconds that need to pass before applying this rule */
01188    int max_value;                      /*!< The amount specified in the penalty rule for max penalty */
01189    int min_value;                      /*!< The amount specified in the penalty rule for min penalty */
01190    int max_relative;                   /*!< Is the max adjustment relative? 1 for relative, 0 for absolute */
01191    int min_relative;                   /*!< Is the min adjustment relative? 1 for relative, 0 for absolute */
01192    AST_LIST_ENTRY(penalty_rule) list;  /*!< Next penalty_rule */
01193 };
01194 
01195 #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */
01196 #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */
01197 #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than <limit>" */
01198 #define ANNOUNCEPOSITION_LIMIT 4 /*!< We not announce position more than <limit> */
01199 
01200 struct call_queue {
01201    AST_DECLARE_STRING_FIELDS(
01202       /*! Queue name */
01203       AST_STRING_FIELD(name);
01204       /*! Music on Hold class */
01205       AST_STRING_FIELD(moh);
01206       /*! Announcement to play when call is answered */
01207       AST_STRING_FIELD(announce);
01208       /*! Exit context */
01209       AST_STRING_FIELD(context);
01210       /*! Macro to run upon member connection */
01211       AST_STRING_FIELD(membermacro);
01212       /*! Gosub to run upon member connection */
01213       AST_STRING_FIELD(membergosub);
01214       /*! Default rule to use if none specified in call to Queue() */
01215       AST_STRING_FIELD(defaultrule);
01216       /*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
01217       AST_STRING_FIELD(sound_next);
01218       /*! Sound file: "There are currently" (def. queue-thereare) */
01219       AST_STRING_FIELD(sound_thereare);
01220       /*! Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting) */
01221       AST_STRING_FIELD(sound_calls);
01222       /*! Sound file: "Currently there are more than" (def. queue-quantity1) */
01223       AST_STRING_FIELD(queue_quantity1);
01224       /*! Sound file: "callers waiting to speak with a representative" (def. queue-quantity2) */
01225       AST_STRING_FIELD(queue_quantity2);
01226       /*! Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */
01227       AST_STRING_FIELD(sound_holdtime);
01228       /*! Sound file: "minutes." (def. queue-minutes) */
01229       AST_STRING_FIELD(sound_minutes);
01230       /*! Sound file: "minute." (def. queue-minute) */
01231       AST_STRING_FIELD(sound_minute);
01232       /*! Sound file: "seconds." (def. queue-seconds) */
01233       AST_STRING_FIELD(sound_seconds);
01234       /*! Sound file: "Thank you for your patience." (def. queue-thankyou) */
01235       AST_STRING_FIELD(sound_thanks);
01236       /*! Sound file: Custom announce for caller, no default */
01237       AST_STRING_FIELD(sound_callerannounce);
01238       /*! Sound file: "Hold time" (def. queue-reporthold) */
01239       AST_STRING_FIELD(sound_reporthold);
01240    );
01241    /*! Sound files: Custom announce, no default */
01242    struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
01243    unsigned int dead:1;
01244    unsigned int eventwhencalled:2;
01245    unsigned int ringinuse:1;
01246    unsigned int announce_to_first_user:1; /*!< Whether or not we announce to the first user in a queue */
01247    unsigned int setinterfacevar:1;
01248    unsigned int setqueuevar:1;
01249    unsigned int setqueueentryvar:1;
01250    unsigned int reportholdtime:1;
01251    unsigned int wrapped:1;
01252    unsigned int timeoutrestart:1;
01253    unsigned int announceholdtime:2;
01254    unsigned int announceposition:3;
01255    int strategy:4;
01256    unsigned int maskmemberstatus:1;
01257    unsigned int realtime:1;
01258    unsigned int found:1;
01259    unsigned int relativeperiodicannounce:1;
01260    unsigned int autopausebusy:1;
01261    unsigned int autopauseunavail:1;
01262    enum empty_conditions joinempty;
01263    enum empty_conditions leavewhenempty;
01264    int announcepositionlimit;          /*!< How many positions we announce? */
01265    int announcefrequency;              /*!< How often to announce their position */
01266    int minannouncefrequency;           /*!< The minimum number of seconds between position announcements (def. 15) */
01267    int periodicannouncefrequency;      /*!< How often to play periodic announcement */
01268    int numperiodicannounce;            /*!< The number of periodic announcements configured */
01269    int randomperiodicannounce;         /*!< Are periodic announcments randomly chosen */
01270    int roundingseconds;                /*!< How many seconds do we round to? */
01271    int holdtime;                       /*!< Current avg holdtime, based on an exponential average */
01272    int talktime;                       /*!< Current avg talktime, based on the same exponential average */
01273    int callscompleted;                 /*!< Number of queue calls completed */
01274    int callsabandoned;                 /*!< Number of queue calls abandoned */
01275    int servicelevel;                   /*!< seconds setting for servicelevel*/
01276    int callscompletedinsl;             /*!< Number of calls answered with servicelevel*/
01277    char monfmt[8];                     /*!< Format to use when recording calls */
01278    int montype;                        /*!< Monitor type  Monitor vs. MixMonitor */
01279    int count;                          /*!< How many entries */
01280    int maxlen;                         /*!< Max number of entries */
01281    int wrapuptime;                     /*!< Wrapup Time */
01282    int penaltymemberslimit;            /*!< Disregard penalty when queue has fewer than this many members */
01283 
01284    int retry;                          /*!< Retry calling everyone after this amount of time */
01285    int timeout;                        /*!< How long to wait for an answer */
01286    int weight;                         /*!< Respective weight */
01287    int autopause;                      /*!< Auto pause queue members if they fail to answer */
01288    int autopausedelay;                 /*!< Delay auto pause for autopausedelay seconds since last call */
01289    int timeoutpriority;                /*!< Do we allow a fraction of the timeout to occur for a ring? */
01290 
01291    /* Queue strategy things */
01292    int rrpos;                          /*!< Round Robin - position */
01293    int memberdelay;                    /*!< Seconds to delay connecting member to caller */
01294    int autofill;                       /*!< Ignore the head call status and ring an available agent */
01295 
01296    struct ao2_container *members;             /*!< Head of the list of members */
01297    struct queue_ent *head;             /*!< Head of the list of callers */
01298    AST_LIST_ENTRY(call_queue) list;    /*!< Next call queue */
01299    AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
01300 };
01301 
01302 struct rule_list {
01303    char name[80];
01304    AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
01305    AST_LIST_ENTRY(rule_list) list;
01306 };
01307 
01308 static AST_LIST_HEAD_STATIC(rule_lists, rule_list);
01309 
01310 static struct ao2_container *queues;
01311 
01312 static void update_realtime_members(struct call_queue *q);
01313 static struct member *interface_exists(struct call_queue *q, const char *interface);
01314 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
01315 
01316 static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
01317 
01318 static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface);
01319 /*! \brief sets the QUEUESTATUS channel variable */
01320 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
01321 {
01322    int i;
01323 
01324    for (i = 0; i < ARRAY_LEN(queue_results); i++) {
01325       if (queue_results[i].id == res) {
01326          pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
01327          return;
01328       }
01329    }
01330 }
01331 
01332 static const char *int2strat(int strategy)
01333 {
01334    int x;
01335 
01336    for (x = 0; x < ARRAY_LEN(strategies); x++) {
01337       if (strategy == strategies[x].strategy) {
01338          return strategies[x].name;
01339       }
01340    }
01341 
01342    return "<unknown>";
01343 }
01344 
01345 static int strat2int(const char *strategy)
01346 {
01347    int x;
01348 
01349    for (x = 0; x < ARRAY_LEN(strategies); x++) {
01350       if (!strcasecmp(strategy, strategies[x].name)) {
01351          return strategies[x].strategy;
01352       }
01353    }
01354 
01355    return -1;
01356 }
01357 
01358 static int autopause2int(const char *autopause)
01359 {
01360    int x;
01361    /*This 'double check' that default value is OFF */
01362    if (ast_strlen_zero(autopause)) {
01363       return QUEUE_AUTOPAUSE_OFF;
01364    }
01365 
01366    /*This 'double check' is to ensure old values works */
01367    if(ast_true(autopause)) {
01368       return QUEUE_AUTOPAUSE_ON;
01369    }
01370 
01371    for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
01372       if (!strcasecmp(autopause, autopausesmodes[x].name)) {
01373          return autopausesmodes[x].autopause;
01374       }
01375    }
01376 
01377    /*This 'double check' that default value is OFF */
01378    return QUEUE_AUTOPAUSE_OFF;
01379 }
01380 
01381 static int queue_hash_cb(const void *obj, const int flags)
01382 {
01383    const struct call_queue *q = obj;
01384 
01385    return ast_str_case_hash(q->name);
01386 }
01387 
01388 static int queue_cmp_cb(void *obj, void *arg, int flags)
01389 {
01390    struct call_queue *q = obj, *q2 = arg;
01391    return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
01392 }
01393 
01394 /*! \internal
01395  * \brief ao2_callback, Decreases queuepos of all followers with a queuepos greater than arg.
01396  * \param obj the member being acted on
01397  * \param arg pointer to an integer containing the position value that was removed and requires reduction for anything above
01398  */
01399 static int queue_member_decrement_followers(void *obj, void *arg, int flag)
01400 {
01401    struct member *mem = obj;
01402    int *decrement_followers_after = arg;
01403 
01404    if (mem->queuepos > *decrement_followers_after) {
01405       mem->queuepos--;
01406    }
01407 
01408    return 0;
01409 }
01410 
01411 /*! \internal
01412  * \brief ao2_callback, finds members in a queue marked for deletion and in a cascading fashion runs queue_member_decrement_followers
01413  *        on them. This callback should always be ran before performing mass unlinking of delmarked members from queues.
01414  * \param obj member being acted on
01415  * \param arg pointer to the queue members are being removed from
01416  */
01417 static int queue_delme_members_decrement_followers(void *obj, void *arg, int flag)
01418 {
01419    struct member *mem = obj;
01420    struct call_queue *queue = arg;
01421    int rrpos = mem->queuepos;
01422 
01423    if (mem->delme) {
01424       ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &rrpos);
01425    }
01426 
01427    return 0;
01428 }
01429 
01430 /*! \internal
01431  * \brief Use this to decrement followers during removal of a member
01432  * \param queue which queue the member is being removed from
01433  * \param mem which member is being removed from the queue
01434  */
01435 static void queue_member_follower_removal(struct call_queue *queue, struct member *mem)
01436 {
01437    int pos = mem->queuepos;
01438 
01439    /* 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
01440     * who would have been next otherwise. */
01441    if (pos < queue->rrpos) {
01442       queue->rrpos--;
01443    }
01444 
01445    ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &pos);
01446 }
01447 
01448 #ifdef REF_DEBUG_ONLY_QUEUES
01449 #define queue_ref(q)          _queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
01450 #define queue_unref(q)           _queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
01451 #define queue_t_ref(q, tag)         _queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01452 #define queue_t_unref(q, tag)    _queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01453 #define queues_t_link(c, q, tag) __ao2_link_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01454 #define queues_t_unlink(c, q, tag)  __ao2_unlink_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01455 
01456 static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
01457 {
01458    __ao2_ref_debug(q, 1, tag, file, line, filename);
01459    return q;
01460 }
01461 
01462 static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
01463 {
01464    __ao2_ref_debug(q, -1, tag, file, line, filename);
01465    return NULL;
01466 }
01467 
01468 #else
01469 
01470 #define queue_t_ref(q, tag)         queue_ref(q)
01471 #define queue_t_unref(q, tag)    queue_unref(q)
01472 #define queues_t_link(c, q, tag) ao2_t_link(c, q, tag)
01473 #define queues_t_unlink(c, q, tag)  ao2_t_unlink(c, q, tag)
01474 
01475 static inline struct call_queue *queue_ref(struct call_queue *q)
01476 {
01477    ao2_ref(q, 1);
01478    return q;
01479 }
01480 
01481 static inline struct call_queue *queue_unref(struct call_queue *q)
01482 {
01483    ao2_ref(q, -1);
01484    return NULL;
01485 }
01486 #endif
01487 
01488 /*! \brief Set variables of queue */
01489 static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
01490 {
01491    char interfacevar[256]="";
01492    float sl = 0;
01493 
01494    ao2_lock(q);
01495 
01496    if (q->setqueuevar) {
01497       sl = 0;
01498       if (q->callscompleted > 0) {
01499          sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
01500       }
01501 
01502       snprintf(interfacevar, sizeof(interfacevar),
01503          "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
01504          q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned,  q->servicelevel, sl);
01505 
01506       ao2_unlock(q);
01507 
01508       pbx_builtin_setvar_multiple(chan, interfacevar);
01509    } else {
01510       ao2_unlock(q);
01511    }
01512 }
01513 
01514 /*! \brief Insert the 'new' entry after the 'prev' entry of queue 'q' */
01515 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
01516 {
01517    struct queue_ent *cur;
01518 
01519    if (!q || !new)
01520       return;
01521    if (prev) {
01522       cur = prev->next;
01523       prev->next = new;
01524    } else {
01525       cur = q->head;
01526       q->head = new;
01527    }
01528    new->next = cur;
01529 
01530    /* every queue_ent must have a reference to it's parent call_queue, this
01531     * reference does not go away until the end of the queue_ent's life, meaning
01532     * that even when the queue_ent leaves the call_queue this ref must remain. */
01533    queue_ref(q);
01534    new->parent = q;
01535    new->pos = ++(*pos);
01536    new->opos = *pos;
01537 }
01538 
01539 /*! \brief Check if members are available
01540  *
01541  * This function checks to see if members are available to be called. If any member
01542  * is available, the function immediately returns 0. If no members are available,
01543  * then -1 is returned.
01544  */
01545 static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions)
01546 {
01547    struct member *member;
01548    struct ao2_iterator mem_iter;
01549 
01550    ao2_lock(q);
01551    mem_iter = ao2_iterator_init(q->members, 0);
01552    for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
01553       if ((max_penalty != INT_MAX && member->penalty > max_penalty) || (min_penalty != INT_MAX && member->penalty < min_penalty)) {
01554          if (conditions & QUEUE_EMPTY_PENALTY) {
01555             ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
01556             continue;
01557          }
01558       }
01559 
01560       switch (member->status) {
01561       case AST_DEVICE_INVALID:
01562          if (conditions & QUEUE_EMPTY_INVALID) {
01563             ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
01564             break;
01565          }
01566          goto default_case;
01567       case AST_DEVICE_UNAVAILABLE:
01568          if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
01569             ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
01570             break;
01571          }
01572          goto default_case;
01573       case AST_DEVICE_INUSE:
01574          if (conditions & QUEUE_EMPTY_INUSE) {
01575             ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
01576             break;
01577          }
01578          goto default_case;
01579       case AST_DEVICE_RINGING:
01580          if (conditions & QUEUE_EMPTY_RINGING) {
01581             ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
01582             break;
01583          }
01584          goto default_case;
01585       case AST_DEVICE_UNKNOWN:
01586          if (conditions & QUEUE_EMPTY_UNKNOWN) {
01587             ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
01588             break;
01589          }
01590          /* Fall-through */
01591       default:
01592       default_case:
01593          if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
01594             ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
01595             break;
01596          } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
01597             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);
01598             break;
01599          } else {
01600             ao2_ref(member, -1);
01601             ao2_iterator_destroy(&mem_iter);
01602             ao2_unlock(q);
01603             ast_debug(4, "%s is available.\n", member->membername);
01604             return 0;
01605          }
01606          break;
01607       }
01608    }
01609    ao2_iterator_destroy(&mem_iter);
01610 
01611    ao2_unlock(q);
01612    return -1;
01613 }
01614 
01615 struct statechange {
01616    AST_LIST_ENTRY(statechange) entry;
01617    int state;
01618    char dev[0];
01619 };
01620 
01621 /*! \brief set a member's status based on device state of that member's state_interface.
01622  *
01623  * Lock interface list find sc, iterate through each queues queue_member list for member to
01624  * update state inside queues
01625 */
01626 static int update_status(struct call_queue *q, struct member *m, const int status)
01627 {
01628    m->status = status;
01629 
01630    if (q->maskmemberstatus) {
01631       return 0;
01632    }
01633 
01634    /*** DOCUMENTATION
01635    <managerEventInstance>
01636       <synopsis>Raised when a Queue member's status has changed.</synopsis>
01637       <syntax>
01638          <parameter name="Queue">
01639             <para>The name of the queue.</para>
01640          </parameter>
01641          <parameter name="Location">
01642             <para>The queue member's channel technology or location.</para>
01643          </parameter>
01644          <parameter name="MemberName">
01645             <para>The name of the queue member.</para>
01646          </parameter>
01647          <parameter name="StateInterface">
01648             <para>Channel technology or location from which to read device state changes.</para>
01649          </parameter>
01650          <parameter name="Membership">
01651             <enumlist>
01652                <enum name="dynamic"/>
01653                <enum name="realtime"/>
01654                <enum name="static"/>
01655             </enumlist>
01656          </parameter>
01657          <parameter name="Penalty">
01658             <para>The penalty associated with the queue member.</para>
01659          </parameter>
01660          <parameter name="CallsTaken">
01661             <para>The number of calls this queue member has serviced.</para>
01662          </parameter>
01663          <parameter name="LastCall">
01664             <para>The time this member last took call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
01665          </parameter>
01666          <parameter name="Status">
01667             <para>The numeric device state status of the queue member.</para>
01668             <enumlist>
01669                <enum name="0"><para>AST_DEVICE_UNKNOWN</para></enum>
01670                <enum name="1"><para>AST_DEVICE_NOT_INUSE</para></enum>
01671                <enum name="2"><para>AST_DEVICE_INUSE</para></enum>
01672                <enum name="3"><para>AST_DEVICE_BUSY</para></enum>
01673                <enum name="4"><para>AST_DEVICE_INVALID</para></enum>
01674                <enum name="5"><para>AST_DEVICE_UNAVAILABLE</para></enum>
01675                <enum name="6"><para>AST_DEVICE_RINGING</para></enum>
01676                <enum name="7"><para>AST_DEVICE_RINGINUSE</para></enum>
01677                <enum name="8"><para>AST_DEVICE_ONHOLD</para></enum>
01678             </enumlist>
01679          </parameter>
01680          <parameter name="Paused">
01681             <enumlist>
01682                <enum name="0"/>
01683                <enum name="1"/>
01684             </enumlist>
01685          </parameter>
01686       </syntax>
01687    </managerEventInstance>
01688    ***/
01689    manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
01690       "Queue: %s\r\n"
01691       "Location: %s\r\n"
01692       "MemberName: %s\r\n"
01693       "StateInterface: %s\r\n"
01694       "Membership: %s\r\n"
01695       "Penalty: %d\r\n"
01696       "CallsTaken: %d\r\n"
01697       "LastCall: %d\r\n"
01698       "Status: %d\r\n"
01699       "Paused: %d\r\n",
01700       q->name, m->interface, m->membername, m->state_interface, m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
01701       m->penalty, m->calls, (int)m->lastcall, m->status, m->paused
01702    );
01703 
01704    return 0;
01705 }
01706 
01707 /*!
01708  * \internal \brief Determine if a queue member is available
01709  * \retval 1 if the member is available
01710  * \retval 0 if the member is not available
01711  */
01712 static int is_member_available(struct call_queue *q, struct member *mem)
01713 {
01714    int available = 0;
01715 
01716    switch (mem->status) {
01717       case AST_DEVICE_INVALID:
01718       case AST_DEVICE_UNAVAILABLE:
01719          break;
01720       case AST_DEVICE_INUSE:
01721       case AST_DEVICE_BUSY:
01722       case AST_DEVICE_RINGING:
01723       case AST_DEVICE_RINGINUSE:
01724       case AST_DEVICE_ONHOLD:
01725          if (!mem->ringinuse) {
01726             break;
01727          }
01728          /* else fall through */
01729       case AST_DEVICE_NOT_INUSE:
01730       case AST_DEVICE_UNKNOWN:
01731          if (!mem->paused) {
01732             available = 1;
01733          }
01734          break;
01735    }
01736 
01737    /* Let wrapuptimes override device state availability */
01738    if (mem->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < mem->lastcall)) {
01739       available = 0;
01740    }
01741    return available;
01742 }
01743 
01744 /*! \brief set a member's status based on device state of that member's interface*/
01745 static int handle_statechange(void *datap)
01746 {
01747    struct statechange *sc = datap;
01748    struct ao2_iterator miter, qiter;
01749    struct member *m;
01750    struct call_queue *q;
01751    char interface[80], *slash_pos;
01752    int found = 0;       /* Found this member in any queue */
01753    int found_member;    /* Found this member in this queue */
01754    int avail = 0;       /* Found an available member in this queue */
01755 
01756    qiter = ao2_iterator_init(queues, 0);
01757    while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
01758       ao2_lock(q);
01759 
01760       avail = 0;
01761       found_member = 0;
01762       miter = ao2_iterator_init(q->members, 0);
01763       for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
01764          if (!found_member) {
01765             ast_copy_string(interface, m->state_interface, sizeof(interface));
01766 
01767             if ((slash_pos = strchr(interface, '/'))) {
01768                if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
01769                   *slash_pos = '\0';
01770                }
01771             }
01772 
01773             if (!strcasecmp(interface, sc->dev)) {
01774                found_member = 1;
01775                update_status(q, m, sc->state);
01776             }
01777          }
01778 
01779          /* check every member until we find one NOT_INUSE */
01780          if (!avail) {
01781             avail = is_member_available(q, m);
01782          }
01783          if (avail && found_member) {
01784             /* early exit as we've found an available member and the member of interest */
01785             ao2_ref(m, -1);
01786             break;
01787          }
01788       }
01789 
01790       if (found_member) {
01791          found = 1;
01792          if (avail) {
01793             ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
01794          } else {
01795             ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
01796          }
01797       }
01798 
01799       ao2_iterator_destroy(&miter);
01800 
01801       ao2_unlock(q);
01802       queue_t_unref(q, "Done with iterator");
01803    }
01804    ao2_iterator_destroy(&qiter);
01805 
01806    if (found) {
01807       ast_debug(1, "Device '%s' changed to state '%d' (%s)\n", sc->dev, sc->state, ast_devstate2str(sc->state));
01808    } else {
01809       ast_debug(3, "Device '%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", sc->dev, sc->state, ast_devstate2str(sc->state));
01810    }
01811 
01812    ast_free(sc);
01813    return 0;
01814 }
01815 
01816 static void device_state_cb(const struct ast_event *event, void *unused)
01817 {
01818    enum ast_device_state state;
01819    const char *device;
01820    struct statechange *sc;
01821    size_t datapsize;
01822 
01823    state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
01824    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
01825 
01826    if (ast_strlen_zero(device)) {
01827       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
01828       return;
01829    }
01830    datapsize = sizeof(*sc) + strlen(device) + 1;
01831    if (!(sc = ast_calloc(1, datapsize))) {
01832       ast_log(LOG_ERROR, "failed to calloc a state change struct\n");
01833       return;
01834    }
01835    sc->state = state;
01836    strcpy(sc->dev, device);
01837    if (ast_taskprocessor_push(devicestate_tps, handle_statechange, sc) < 0) {
01838       ast_free(sc);
01839    }
01840 }
01841 
01842 /*! \brief Helper function which converts from extension state to device state values */
01843 static int extensionstate2devicestate(int state)
01844 {
01845    switch (state) {
01846    case AST_EXTENSION_NOT_INUSE:
01847       state = AST_DEVICE_NOT_INUSE;
01848       break;
01849    case AST_EXTENSION_INUSE:
01850       state = AST_DEVICE_INUSE;
01851       break;
01852    case AST_EXTENSION_BUSY:
01853       state = AST_DEVICE_BUSY;
01854       break;
01855    case AST_EXTENSION_RINGING:
01856       state = AST_DEVICE_RINGING;
01857       break;
01858    case AST_EXTENSION_ONHOLD:
01859       state = AST_DEVICE_ONHOLD;
01860       break;
01861    case AST_EXTENSION_UNAVAILABLE:
01862       state = AST_DEVICE_UNAVAILABLE;
01863       break;
01864    case AST_EXTENSION_REMOVED:
01865    case AST_EXTENSION_DEACTIVATED:
01866    default:
01867       state = AST_DEVICE_INVALID;
01868       break;
01869    }
01870 
01871    return state;
01872 }
01873 
01874 static int extension_state_cb(char *context, char *exten, struct ast_state_cb_info *info, void *data)
01875 {
01876    struct ao2_iterator miter, qiter;
01877    struct member *m;
01878    struct call_queue *q;
01879    int state = info->exten_state;
01880    int found = 0, device_state = extensionstate2devicestate(state);
01881 
01882    /* only interested in extension state updates involving device states */
01883    if (info->reason != AST_HINT_UPDATE_DEVICE) {
01884       return 0;
01885    }
01886 
01887    qiter = ao2_iterator_init(queues, 0);
01888    while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
01889       ao2_lock(q);
01890 
01891       miter = ao2_iterator_init(q->members, 0);
01892       for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
01893          if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
01894             update_status(q, m, device_state);
01895             ao2_ref(m, -1);
01896             found = 1;
01897             break;
01898          }
01899       }
01900       ao2_iterator_destroy(&miter);
01901 
01902       ao2_unlock(q);
01903       queue_t_unref(q, "Done with iterator");
01904    }
01905    ao2_iterator_destroy(&qiter);
01906 
01907         if (found) {
01908       ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
01909    } else {
01910       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",
01911            exten, context, device_state, ast_devstate2str(device_state));
01912    }
01913 
01914    return 0;
01915 }
01916 
01917 /*! \brief Return the current state of a member */
01918 static int get_queue_member_status(struct member *cur)
01919 {
01920    return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
01921 }
01922 
01923 /*! \brief allocate space for new queue member and set fields based on parameters passed */
01924 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
01925 {
01926    struct member *cur;
01927 
01928    if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
01929       cur->ringinuse = ringinuse;
01930       cur->penalty = penalty;
01931       cur->paused = paused;
01932       ast_copy_string(cur->interface, interface, sizeof(cur->interface));
01933       if (!ast_strlen_zero(state_interface)) {
01934          ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
01935       } else {
01936          ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
01937       }
01938       if (!ast_strlen_zero(membername)) {
01939          ast_copy_string(cur->membername, membername, sizeof(cur->membername));
01940       } else {
01941          ast_copy_string(cur->membername, interface, sizeof(cur->membername));
01942       }
01943       if (!strchr(cur->interface, '/')) {
01944          ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
01945       }
01946       if (!strncmp(cur->state_interface, "hint:", 5)) {
01947          char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
01948          char *exten = strsep(&context, "@") + 5;
01949 
01950          ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
01951          ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
01952       }
01953       cur->status = get_queue_member_status(cur);
01954    }
01955 
01956    return cur;
01957 }
01958 
01959 
01960 static int compress_char(const char c)
01961 {
01962    if (c < 32) {
01963       return 0;
01964    } else if (c > 96) {
01965       return c - 64;
01966    }
01967    return c - 32;
01968 }
01969 
01970 static int member_hash_fn(const void *obj, const int flags)
01971 {
01972    const struct member *mem = obj;
01973    const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
01974    const char *chname = strchr(interface, '/');
01975    int ret = 0, i;
01976 
01977    if (!chname) {
01978       chname = interface;
01979    }
01980    for (i = 0; i < 5 && chname[i]; i++) {
01981       ret += compress_char(chname[i]) << (i * 6);
01982    }
01983    return ret;
01984 }
01985 
01986 static int member_cmp_fn(void *obj1, void *obj2, int flags)
01987 {
01988    struct member *mem1 = obj1;
01989    struct member *mem2 = obj2;
01990    const char *interface = (flags & OBJ_KEY) ? obj2 : mem2->interface;
01991 
01992    return strcasecmp(mem1->interface, interface) ? 0 : CMP_MATCH | CMP_STOP;
01993 }
01994 
01995 /*!
01996  * \brief Initialize Queue default values.
01997  * \note the queue's lock  must be held before executing this function
01998 */
01999 static void init_queue(struct call_queue *q)
02000 {
02001    int i;
02002    struct penalty_rule *pr_iter;
02003 
02004    q->dead = 0;
02005    q->retry = DEFAULT_RETRY;
02006    q->timeout = DEFAULT_TIMEOUT;
02007    q->maxlen = 0;
02008    q->announcefrequency = 0;
02009    q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
02010    q->announceholdtime = 1;
02011    q->announcepositionlimit = 10; /* Default 10 positions */
02012    q->announceposition = ANNOUNCEPOSITION_YES; /* Default yes */
02013    q->roundingseconds = 0; /* Default - don't announce seconds */
02014    q->servicelevel = 0;
02015    q->ringinuse = 1;
02016    q->announce_to_first_user = 0;
02017    q->setinterfacevar = 0;
02018    q->setqueuevar = 0;
02019    q->setqueueentryvar = 0;
02020    q->autofill = autofill_default;
02021    q->montype = montype_default;
02022    q->monfmt[0] = '\0';
02023    q->reportholdtime = 0;
02024    q->wrapuptime = 0;
02025    q->penaltymemberslimit = 0;
02026    q->joinempty = 0;
02027    q->leavewhenempty = 0;
02028    q->memberdelay = 0;
02029    q->maskmemberstatus = 0;
02030    q->eventwhencalled = 0;
02031    q->weight = 0;
02032    q->timeoutrestart = 0;
02033    q->periodicannouncefrequency = 0;
02034    q->randomperiodicannounce = 0;
02035    q->numperiodicannounce = 0;
02036    q->autopause = QUEUE_AUTOPAUSE_OFF;
02037    q->timeoutpriority = TIMEOUT_PRIORITY_APP;
02038    q->autopausedelay = 0;
02039    if (!q->members) {
02040       if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED) {
02041          /* linear strategy depends on order, so we have to place all members in a single bucket */
02042          q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
02043       } else {
02044          q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
02045       }
02046    }
02047    q->found = 1;
02048 
02049    ast_string_field_set(q, sound_next, "queue-youarenext");
02050    ast_string_field_set(q, sound_thereare, "queue-thereare");
02051    ast_string_field_set(q, sound_calls, "queue-callswaiting");
02052    ast_string_field_set(q, queue_quantity1, "queue-quantity1");
02053    ast_string_field_set(q, queue_quantity2, "queue-quantity2");
02054    ast_string_field_set(q, sound_holdtime, "queue-holdtime");
02055    ast_string_field_set(q, sound_minutes, "queue-minutes");
02056    ast_string_field_set(q, sound_minute, "queue-minute");
02057    ast_string_field_set(q, sound_seconds, "queue-seconds");
02058    ast_string_field_set(q, sound_thanks, "queue-thankyou");
02059    ast_string_field_set(q, sound_reporthold, "queue-reporthold");
02060 
02061    if (!q->sound_periodicannounce[0]) {
02062       q->sound_periodicannounce[0] = ast_str_create(32);
02063    }
02064 
02065    if (q->sound_periodicannounce[0]) {
02066       ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
02067    }
02068 
02069    for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
02070       if (q->sound_periodicannounce[i]) {
02071          ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
02072       }
02073    }
02074 
02075    while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list))) {
02076       ast_free(pr_iter);
02077    }
02078 
02079    /* On restart assume no members are available.
02080     * The queue_avail hint is a boolean state to indicate whether a member is available or not.
02081     *
02082     * This seems counter intuitive, but is required to light a BLF
02083     * AST_DEVICE_INUSE indicates no members are available.
02084     * AST_DEVICE_NOT_INUSE indicates a member is available.
02085     */
02086    ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
02087 }
02088 
02089 static void clear_queue(struct call_queue *q)
02090 {
02091    q->holdtime = 0;
02092    q->callscompleted = 0;
02093    q->callsabandoned = 0;
02094    q->callscompletedinsl = 0;
02095    q->talktime = 0;
02096 
02097    if (q->members) {
02098       struct member *mem;
02099       struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
02100       while ((mem = ao2_iterator_next(&mem_iter))) {
02101          mem->calls = 0;
02102          mem->lastcall = 0;
02103          ao2_ref(mem, -1);
02104       }
02105       ao2_iterator_destroy(&mem_iter);
02106    }
02107 }
02108 
02109 /*!
02110  * \brief Change queue penalty by adding rule.
02111  *
02112  * Check rule for errors with time or fomatting, see if rule is relative to rest
02113  * of queue, iterate list of rules to find correct insertion point, insert and return.
02114  * \retval -1 on failure
02115  * \retval 0 on success
02116  * \note Call this with the rule_lists locked
02117 */
02118 static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
02119 {
02120    char *timestr, *maxstr, *minstr, *contentdup;
02121    struct penalty_rule *rule = NULL, *rule_iter;
02122    struct rule_list *rl_iter;
02123    int penaltychangetime, inserted = 0;
02124 
02125    if (!(rule = ast_calloc(1, sizeof(*rule)))) {
02126       return -1;
02127    }
02128 
02129    contentdup = ast_strdupa(content);
02130 
02131    if (!(maxstr = strchr(contentdup, ','))) {
02132       ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
02133       ast_free(rule);
02134       return -1;
02135    }
02136 
02137    *maxstr++ = '\0';
02138    timestr = contentdup;
02139 
02140    if ((penaltychangetime = atoi(timestr)) < 0) {
02141       ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
02142       ast_free(rule);
02143       return -1;
02144    }
02145 
02146    rule->time = penaltychangetime;
02147 
02148    if ((minstr = strchr(maxstr,','))) {
02149       *minstr++ = '\0';
02150    }
02151 
02152    /* The last check will evaluate true if either no penalty change is indicated for a given rule
02153     * OR if a min penalty change is indicated but no max penalty change is */
02154    if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
02155       rule->max_relative = 1;
02156    }
02157 
02158    rule->max_value = atoi(maxstr);
02159 
02160    if (!ast_strlen_zero(minstr)) {
02161       if (*minstr == '+' || *minstr == '-') {
02162          rule->min_relative = 1;
02163       }
02164       rule->min_value = atoi(minstr);
02165    } else { /*there was no minimum specified, so assume this means no change*/
02166       rule->min_relative = 1;
02167    }
02168 
02169    /*We have the rule made, now we need to insert it where it belongs*/
02170    AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
02171       if (strcasecmp(rl_iter->name, list_name)) {
02172          continue;
02173       }
02174 
02175       AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
02176          if (rule->time < rule_iter->time) {
02177             AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
02178             inserted = 1;
02179             break;
02180          }
02181       }
02182       AST_LIST_TRAVERSE_SAFE_END;
02183 
02184       if (!inserted) {
02185          AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
02186          inserted = 1;
02187       }
02188 
02189       break;
02190    }
02191 
02192    if (!inserted) {
02193       ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name);
02194       ast_free(rule);
02195       return -1;
02196    }
02197    return 0;
02198 }
02199 
02200 static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
02201 {
02202    char *value_copy = ast_strdupa(value);
02203    char *option = NULL;
02204    while ((option = strsep(&value_copy, ","))) {
02205       if (!strcasecmp(option, "paused")) {
02206          *empty |= QUEUE_EMPTY_PAUSED;
02207       } else if (!strcasecmp(option, "penalty")) {
02208          *empty |= QUEUE_EMPTY_PENALTY;
02209       } else if (!strcasecmp(option, "inuse")) {
02210          *empty |= QUEUE_EMPTY_INUSE;
02211       } else if (!strcasecmp(option, "ringing")) {
02212          *empty |= QUEUE_EMPTY_RINGING;
02213       } else if (!strcasecmp(option, "invalid")) {
02214          *empty |= QUEUE_EMPTY_INVALID;
02215       } else if (!strcasecmp(option, "wrapup")) {
02216          *empty |= QUEUE_EMPTY_WRAPUP;
02217       } else if (!strcasecmp(option, "unavailable")) {
02218          *empty |= QUEUE_EMPTY_UNAVAILABLE;
02219       } else if (!strcasecmp(option, "unknown")) {
02220          *empty |= QUEUE_EMPTY_UNKNOWN;
02221       } else if (!strcasecmp(option, "loose")) {
02222          *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID);
02223       } else if (!strcasecmp(option, "strict")) {
02224          *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED | QUEUE_EMPTY_UNAVAILABLE);
02225       } else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
02226          *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED);
02227       } else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
02228          *empty = 0;
02229       } else {
02230          ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
02231       }
02232    }
02233 }
02234 
02235 /*! \brief Configure a queue parameter.
02236  *
02237  * The failunknown flag is set for config files (and static realtime) to show
02238  * errors for unknown parameters. It is cleared for dynamic realtime to allow
02239  *  extra fields in the tables.
02240  * \note For error reporting, line number is passed for .conf static configuration,
02241  * for Realtime queues, linenum is -1.
02242 */
02243 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
02244 {
02245    if (!strcasecmp(param, "musicclass") ||
02246       !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
02247       ast_string_field_set(q, moh, val);
02248    } else if (!strcasecmp(param, "announce")) {
02249       ast_string_field_set(q, announce, val);
02250    } else if (!strcasecmp(param, "context")) {
02251       ast_string_field_set(q, context, val);
02252    } else if (!strcasecmp(param, "timeout")) {
02253       q->timeout = atoi(val);
02254       if (q->timeout < 0) {
02255          q->timeout = DEFAULT_TIMEOUT;
02256       }
02257    } else if (!strcasecmp(param, "ringinuse")) {
02258       q->ringinuse = ast_true(val);
02259    } else if (!strcasecmp(param, "setinterfacevar")) {
02260       q->setinterfacevar = ast_true(val);
02261    } else if (!strcasecmp(param, "setqueuevar")) {
02262       q->setqueuevar = ast_true(val);
02263    } else if (!strcasecmp(param, "setqueueentryvar")) {
02264       q->setqueueentryvar = ast_true(val);
02265    } else if (!strcasecmp(param, "monitor-format")) {
02266       ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
02267    } else if (!strcasecmp(param, "membermacro")) {
02268       ast_string_field_set(q, membermacro, val);
02269    } else if (!strcasecmp(param, "membergosub")) {
02270       ast_string_field_set(q, membergosub, val);
02271    } else if (!strcasecmp(param, "queue-youarenext")) {
02272       ast_string_field_set(q, sound_next, val);
02273    } else if (!strcasecmp(param, "queue-thereare")) {
02274       ast_string_field_set(q, sound_thereare, val);
02275    } else if (!strcasecmp(param, "queue-callswaiting")) {
02276       ast_string_field_set(q, sound_calls, val);
02277    } else if (!strcasecmp(param, "queue-quantity1")) {
02278       ast_string_field_set(q, queue_quantity1, val);
02279    } else if (!strcasecmp(param, "queue-quantity2")) {
02280       ast_string_field_set(q, queue_quantity2, val);
02281    } else if (!strcasecmp(param, "queue-holdtime")) {
02282       ast_string_field_set(q, sound_holdtime, val);
02283    } else if (!strcasecmp(param, "queue-minutes")) {
02284       ast_string_field_set(q, sound_minutes, val);
02285    } else if (!strcasecmp(param, "queue-minute")) {
02286       ast_string_field_set(q, sound_minute, val);
02287    } else if (!strcasecmp(param, "queue-seconds")) {
02288       ast_string_field_set(q, sound_seconds, val);
02289    } else if (!strcasecmp(param, "queue-thankyou")) {
02290       ast_string_field_set(q, sound_thanks, val);
02291    } else if (!strcasecmp(param, "queue-callerannounce")) {
02292       ast_string_field_set(q, sound_callerannounce, val);
02293    } else if (!strcasecmp(param, "queue-reporthold")) {
02294       ast_string_field_set(q, sound_reporthold, val);
02295    } else if (!strcasecmp(param, "announce-frequency")) {
02296       q->announcefrequency = atoi(val);
02297    } else if (!strcasecmp(param, "announce-to-first-user")) {
02298       q->announce_to_first_user = ast_true(val);
02299    } else if (!strcasecmp(param, "min-announce-frequency")) {
02300       q->minannouncefrequency = atoi(val);
02301       ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
02302    } else if (!strcasecmp(param, "announce-round-seconds")) {
02303       q->roundingseconds = atoi(val);
02304       /* Rounding to any other values just doesn't make sense... */
02305       if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
02306          || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
02307          if (linenum >= 0) {
02308             ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
02309                "using 0 instead for queue '%s' at line %d of queues.conf\n",
02310                val, param, q->name, linenum);
02311          } else {
02312             ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
02313                "using 0 instead for queue '%s'\n", val, param, q->name);
02314          }
02315          q->roundingseconds=0;
02316       }
02317    } else if (!strcasecmp(param, "announce-holdtime")) {
02318       if (!strcasecmp(val, "once")) {
02319          q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
02320       } else if (ast_true(val)) {
02321          q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
02322       } else {
02323          q->announceholdtime = 0;
02324       }
02325    } else if (!strcasecmp(param, "announce-position")) {
02326       if (!strcasecmp(val, "limit")) {
02327          q->announceposition = ANNOUNCEPOSITION_LIMIT;
02328       } else if (!strcasecmp(val, "more")) {
02329          q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
02330       } else if (ast_true(val)) {
02331          q->announceposition = ANNOUNCEPOSITION_YES;
02332       } else {
02333          q->announceposition = ANNOUNCEPOSITION_NO;
02334       }
02335    } else if (!strcasecmp(param, "announce-position-limit")) {
02336       q->announcepositionlimit = atoi(val);
02337    } else if (!strcasecmp(param, "periodic-announce")) {
02338       if (strchr(val, ',')) {
02339          char *s, *buf = ast_strdupa(val);
02340          unsigned int i = 0;
02341 
02342          while ((s = strsep(&buf, ",|"))) {
02343             if (!q->sound_periodicannounce[i]) {
02344                q->sound_periodicannounce[i] = ast_str_create(16);
02345             }
02346             ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
02347             i++;
02348             if (i == MAX_PERIODIC_ANNOUNCEMENTS) {
02349                break;
02350             }
02351          }
02352          q->numperiodicannounce = i;
02353       } else {
02354          ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
02355          q->numperiodicannounce = 1;
02356       }
02357    } else if (!strcasecmp(param, "periodic-announce-frequency")) {
02358       q->periodicannouncefrequency = atoi(val);
02359    } else if (!strcasecmp(param, "relative-periodic-announce")) {
02360       q->relativeperiodicannounce = ast_true(val);
02361    } else if (!strcasecmp(param, "random-periodic-announce")) {
02362       q->randomperiodicannounce = ast_true(val);
02363    } else if (!strcasecmp(param, "retry")) {
02364       q->retry = atoi(val);
02365       if (q->retry <= 0) {
02366          q->retry = DEFAULT_RETRY;
02367       }
02368    } else if (!strcasecmp(param, "wrapuptime")) {
02369       q->wrapuptime = atoi(val);
02370    } else if (!strcasecmp(param, "penaltymemberslimit")) {
02371       if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
02372          q->penaltymemberslimit = 0;
02373       }
02374    } else if (!strcasecmp(param, "autofill")) {
02375       q->autofill = ast_true(val);
02376    } else if (!strcasecmp(param, "monitor-type")) {
02377       if (!strcasecmp(val, "mixmonitor")) {
02378          q->montype = 1;
02379       }
02380    } else if (!strcasecmp(param, "autopause")) {
02381       q->autopause = autopause2int(val);
02382    } else if (!strcasecmp(param, "autopausedelay")) {
02383       q->autopausedelay = atoi(val);
02384    } else if (!strcasecmp(param, "autopausebusy")) {
02385       q->autopausebusy = ast_true(val);
02386    } else if (!strcasecmp(param, "autopauseunavail")) {
02387       q->autopauseunavail = ast_true(val);
02388    } else if (!strcasecmp(param, "maxlen")) {
02389       q->maxlen = atoi(val);
02390       if (q->maxlen < 0) {
02391          q->maxlen = 0;
02392       }
02393    } else if (!strcasecmp(param, "servicelevel")) {
02394       q->servicelevel= atoi(val);
02395    } else if (!strcasecmp(param, "strategy")) {
02396       int strategy;
02397 
02398       /* We are a static queue and already have set this, no need to do it again */
02399       if (failunknown) {
02400          return;
02401       }
02402       strategy = strat2int(val);
02403       if (strategy < 0) {
02404          ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
02405             val, q->name);
02406          q->strategy = QUEUE_STRATEGY_RINGALL;
02407       }
02408       if (strategy == q->strategy) {
02409          return;
02410       }
02411       if (strategy == QUEUE_STRATEGY_LINEAR) {
02412          ast_log(LOG_WARNING, "Changing to the linear strategy currently requires asterisk to be restarted.\n");
02413          return;
02414       }
02415       q->strategy = strategy;
02416    } else if (!strcasecmp(param, "joinempty")) {
02417       parse_empty_options(val, &q->joinempty, 1);
02418    } else if (!strcasecmp(param, "leavewhenempty")) {
02419       parse_empty_options(val, &q->leavewhenempty, 0);
02420    } else if (!strcasecmp(param, "eventmemberstatus")) {
02421       q->maskmemberstatus = !ast_true(val);
02422    } else if (!strcasecmp(param, "eventwhencalled")) {
02423       if (!strcasecmp(val, "vars")) {
02424          q->eventwhencalled = QUEUE_EVENT_VARIABLES;
02425       } else {
02426          q->eventwhencalled = ast_true(val) ? 1 : 0;
02427       }
02428    } else if (!strcasecmp(param, "reportholdtime")) {
02429       q->reportholdtime = ast_true(val);
02430    } else if (!strcasecmp(param, "memberdelay")) {
02431       q->memberdelay = atoi(val);
02432    } else if (!strcasecmp(param, "weight")) {
02433       q->weight = atoi(val);
02434    } else if (!strcasecmp(param, "timeoutrestart")) {
02435       q->timeoutrestart = ast_true(val);
02436    } else if (!strcasecmp(param, "defaultrule")) {
02437       ast_string_field_set(q, defaultrule, val);
02438    } else if (!strcasecmp(param, "timeoutpriority")) {
02439       if (!strcasecmp(val, "conf")) {
02440          q->timeoutpriority = TIMEOUT_PRIORITY_CONF;
02441       } else {
02442          q->timeoutpriority = TIMEOUT_PRIORITY_APP;
02443       }
02444    } else if (failunknown) {
02445       if (linenum >= 0) {
02446          ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
02447             q->name, param, linenum);
02448       } else {
02449          ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
02450       }
02451    }
02452 }
02453 
02454 /*! \internal
02455  * \brief If adding a single new member to a queue, use this function instead of ao2_linking.
02456  *        This adds round robin queue position data for a fresh member as well as links it.
02457  * \param queue Which queue the member is being added to
02458  * \param mem Which member is being added to the queue
02459  */
02460 static void member_add_to_queue(struct call_queue *queue, struct member *mem)
02461 {
02462    ao2_lock(queue->members);
02463    mem->queuepos = ao2_container_count(queue->members);
02464    ao2_link(queue->members, mem);
02465    ao2_unlock(queue->members);
02466 }
02467 
02468 /*! \internal
02469  * \brief If removing a single member from a queue, use this function instead of ao2_unlinking.
02470  *        This will perform round robin queue position reordering for the remaining members.
02471  * \param queue Which queue the member is being removed from
02472  * \param member Which member is being removed from the queue
02473  */
02474 static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
02475 {
02476    ao2_lock(queue->members);
02477    queue_member_follower_removal(queue, mem);
02478    ao2_unlink(queue->members, mem);
02479    ao2_unlock(queue->members);
02480 }
02481 
02482 /*!
02483  * \brief Find rt member record to update otherwise create one.
02484  *
02485  * Search for member in queue, if found update penalty/paused state,
02486  * if no member exists create one flag it as a RT member and add to queue member list.
02487 */
02488 static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config)
02489 {
02490    struct member *m;
02491    struct ao2_iterator mem_iter;
02492    int penalty = 0;
02493    int paused  = 0;
02494    int found = 0;
02495    int ringinuse = q->ringinuse;
02496 
02497    const char *config_val;
02498    const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
02499    const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface);
02500    const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface);
02501    const char *penalty_str = ast_variable_retrieve(member_config, interface, "penalty");
02502    const char *paused_str = ast_variable_retrieve(member_config, interface, "paused");
02503 
02504    if (ast_strlen_zero(rt_uniqueid)) {
02505       ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));
02506       return;
02507    }
02508 
02509    if (penalty_str) {
02510       penalty = atoi(penalty_str);
02511       if ((penalty < 0) && negative_penalty_invalid) {
02512          return;
02513       } else if (penalty < 0) {
02514          penalty = 0;
02515       }
02516    }
02517 
02518    if (paused_str) {
02519       paused = atoi(paused_str);
02520       if (paused < 0) {
02521          paused = 0;
02522       }
02523    }
02524 
02525    if ((config_val = ast_variable_retrieve(member_config, interface, realtime_ringinuse_field))) {
02526       if (ast_true(config_val)) {
02527          ringinuse = 1;
02528       } else if (ast_false(config_val)) {
02529          ringinuse = 0;
02530       } else {
02531          ast_log(LOG_WARNING, "Invalid value of '%s' field for %s in queue '%s'\n", realtime_ringinuse_field, interface, q->name);
02532       }
02533    }
02534 
02535    /* Find member by realtime uniqueid and update */
02536    mem_iter = ao2_iterator_init(q->members, 0);
02537    while ((m = ao2_iterator_next(&mem_iter))) {
02538       if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
02539          m->dead = 0;   /* Do not delete this one. */
02540          ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
02541          if (paused_str) {
02542             m->paused = paused;
02543          }
02544          if (strcasecmp(state_interface, m->state_interface)) {
02545             ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
02546          }
02547          m->penalty = penalty;
02548          m->ringinuse = ringinuse;
02549          found = 1;
02550          ao2_ref(m, -1);
02551          break;
02552       }
02553       ao2_ref(m, -1);
02554    }
02555    ao2_iterator_destroy(&mem_iter);
02556 
02557    /* Create a new member */
02558    if (!found) {
02559       if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse))) {
02560          m->dead = 0;
02561          m->realtime = 1;
02562          ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
02563          if (!log_membername_as_agent) {
02564             ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
02565          } else {
02566             ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
02567          }
02568          member_add_to_queue(q, m);
02569          ao2_ref(m, -1);
02570          m = NULL;
02571       }
02572    }
02573 }
02574 
02575 /*! \brief Iterate through queue's member list and delete them */
02576 static void free_members(struct call_queue *q, int all)
02577 {
02578    /* Free non-dynamic members */
02579    struct member *cur;
02580    struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
02581 
02582    while ((cur = ao2_iterator_next(&mem_iter))) {
02583       if (all || !cur->dynamic) {
02584          member_remove_from_queue(q, cur);
02585       }
02586       ao2_ref(cur, -1);
02587    }
02588    ao2_iterator_destroy(&mem_iter);
02589 }
02590 
02591 /*! \brief Free queue's member list then its string fields */
02592 static void destroy_queue(void *obj)
02593 {
02594    struct call_queue *q = obj;
02595    int i;
02596 
02597    free_members(q, 1);
02598    ast_string_field_free_memory(q);
02599    for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
02600       if (q->sound_periodicannounce[i]) {
02601          free(q->sound_periodicannounce[i]);
02602       }
02603    }
02604    ao2_ref(q->members, -1);
02605 }
02606 
02607 static struct call_queue *alloc_queue(const char *queuename)
02608 {
02609    struct call_queue *q;
02610 
02611    if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
02612       if (ast_string_field_init(q, 64)) {
02613          queue_t_unref(q, "String field allocation failed");
02614          return NULL;
02615       }
02616       ast_string_field_set(q, name, queuename);
02617    }
02618    return q;
02619 }
02620 
02621 /*!
02622  * \brief Reload a single queue via realtime.
02623  *
02624  * Check for statically defined queue first, check if deleted RT queue,
02625  * check for new RT queue, if queue vars are not defined init them with defaults.
02626  * reload RT queue vars, set RT queue members dead and reload them, return finished queue.
02627  * \retval the queue,
02628  * \retval NULL if it doesn't exist.
02629  * \note Should be called with the "queues" container locked.
02630 */
02631 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
02632 {
02633    struct ast_variable *v;
02634    struct call_queue *q, tmpq = {
02635       .name = queuename,
02636    };
02637    struct member *m;
02638    struct ao2_iterator mem_iter;
02639    char *interface = NULL;
02640    const char *tmp_name;
02641    char *tmp;
02642    char tmpbuf[64];  /* Must be longer than the longest queue param name. */
02643 
02644    /* Static queues override realtime. */
02645    if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
02646       ao2_lock(q);
02647       if (!q->realtime) {
02648          if (q->dead) {
02649             ao2_unlock(q);
02650             queue_t_unref(q, "Queue is dead; can't return it");
02651             return NULL;
02652          }
02653          ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
02654          ao2_unlock(q);
02655          return q;
02656       }
02657    } else if (!member_config) {
02658       /* Not found in the list, and it's not realtime ... */
02659       return NULL;
02660    }
02661    /* Check if queue is defined in realtime. */
02662    if (!queue_vars) {
02663       /* Delete queue from in-core list if it has been deleted in realtime. */
02664       if (q) {
02665          /*! \note Hmm, can't seem to distinguish a DB failure from a not
02666             found condition... So we might delete an in-core queue
02667             in case of DB failure. */
02668          ast_debug(1, "Queue %s not found in realtime.\n", queuename);
02669 
02670          q->dead = 1;
02671          /* Delete if unused (else will be deleted when last caller leaves). */
02672          queues_t_unlink(queues, q, "Unused; removing from container");
02673          ao2_unlock(q);
02674          queue_t_unref(q, "Queue is dead; can't return it");
02675       }
02676       return NULL;
02677    }
02678 
02679    /* Create a new queue if an in-core entry does not exist yet. */
02680    if (!q) {
02681       struct ast_variable *tmpvar = NULL;
02682       if (!(q = alloc_queue(queuename))) {
02683          return NULL;
02684       }
02685       ao2_lock(q);
02686       clear_queue(q);
02687       q->realtime = 1;
02688       /*Before we initialize the queue, we need to set the strategy, so that linear strategy
02689        * will allocate the members properly
02690        */
02691       for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
02692          if (!strcasecmp(tmpvar->name, "strategy")) {
02693             q->strategy = strat2int(tmpvar->value);
02694             if (q->strategy < 0) {
02695                ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
02696                tmpvar->value, q->name);
02697                q->strategy = QUEUE_STRATEGY_RINGALL;
02698             }
02699             break;
02700          }
02701       }
02702       /* We traversed all variables and didn't find a strategy */
02703       if (!tmpvar) {
02704          q->strategy = QUEUE_STRATEGY_RINGALL;
02705       }
02706       queues_t_link(queues, q, "Add queue to container");
02707    }
02708    init_queue(q);    /* Ensure defaults for all parameters not set explicitly. */
02709 
02710    memset(tmpbuf, 0, sizeof(tmpbuf));
02711    for (v = queue_vars; v; v = v->next) {
02712       /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
02713       if (strchr(v->name, '_')) {
02714          ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
02715          tmp_name = tmpbuf;
02716          tmp = tmpbuf;
02717          while ((tmp = strchr(tmp, '_'))) {
02718             *tmp++ = '-';
02719          }
02720       } else {
02721          tmp_name = v->name;
02722       }
02723 
02724       /* NULL values don't get returned from realtime; blank values should
02725        * still get set.  If someone doesn't want a value to be set, they
02726        * should set the realtime column to NULL, not blank. */
02727       queue_set_param(q, tmp_name, v->value, -1, 0);
02728    }
02729 
02730    /* Temporarily set realtime members dead so we can detect deleted ones. */
02731    mem_iter = ao2_iterator_init(q->members, 0);
02732    while ((m = ao2_iterator_next(&mem_iter))) {
02733       if (m->realtime) {
02734          m->dead = 1;
02735       }
02736       ao2_ref(m, -1);
02737    }
02738    ao2_iterator_destroy(&mem_iter);
02739 
02740    while ((interface = ast_category_browse(member_config, interface))) {
02741       rt_handle_member_record(q, interface, member_config);
02742    }
02743 
02744    /* Delete all realtime members that have been deleted in DB. */
02745    mem_iter = ao2_iterator_init(q->members, 0);
02746    while ((m = ao2_iterator_next(&mem_iter))) {
02747       if (m->dead) {
02748          if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
02749             ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
02750          } else {
02751             ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
02752          }
02753          member_remove_from_queue(q, m);
02754       }
02755       ao2_ref(m, -1);
02756    }
02757    ao2_iterator_destroy(&mem_iter);
02758 
02759    ao2_unlock(q);
02760 
02761    return q;
02762 }
02763 
02764 /*!
02765  * note  */
02766 
02767 /*!
02768  * \internal
02769  * \brief Returns reference to the named queue. If the queue is realtime, it will load the queue as well.
02770  * \param queuename - name of the desired queue
02771  *
02772  * \retval the queue
02773  * \retval NULL if it doesn't exist
02774  */
02775 static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
02776 {
02777    struct ast_variable *queue_vars;
02778    struct ast_config *member_config = NULL;
02779    struct call_queue *q = NULL, tmpq = {
02780       .name = queuename,
02781    };
02782    int prev_weight = 0;
02783 
02784    /* Find the queue in the in-core list first. */
02785    q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
02786 
02787    if (!q || q->realtime) {
02788       /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
02789          queue operations while waiting for the DB.
02790 
02791          This will be two separate database transactions, so we might
02792          see queue parameters as they were before another process
02793          changed the queue and member list as it was after the change.
02794          Thus we might see an empty member list when a queue is
02795          deleted. In practise, this is unlikely to cause a problem. */
02796 
02797       queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
02798       if (queue_vars) {
02799          member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
02800          if (!member_config) {
02801             ast_debug(1, "No queue_members defined in config extconfig.conf\n");
02802             member_config = ast_config_new();
02803          }
02804       }
02805       if (q) {
02806          prev_weight = q->weight ? 1 : 0;
02807          queue_t_unref(q, "Need to find realtime queue");
02808       }
02809 
02810       q = find_queue_by_name_rt(queuename, queue_vars, member_config);
02811       ast_config_destroy(member_config);
02812       ast_variables_destroy(queue_vars);
02813 
02814       /* update the use_weight value if the queue's has gained or lost a weight */
02815       if (q) {
02816          if (!q->weight && prev_weight) {
02817             ast_atomic_fetchadd_int(&use_weight, -1);
02818          }
02819          if (q->weight && !prev_weight) {
02820             ast_atomic_fetchadd_int(&use_weight, +1);
02821          }
02822       }
02823       /* Other cases will end up with the proper value for use_weight */
02824    } else {
02825       update_realtime_members(q);
02826    }
02827    return q;
02828 }
02829 
02830 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
02831 {
02832    int ret = -1;
02833 
02834    if (ast_strlen_zero(mem->rt_uniqueid)) {
02835       return ret;
02836    }
02837 
02838    if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) > 0) {
02839       ret = 0;
02840    }
02841 
02842    return ret;
02843 }
02844 
02845 
02846 static void update_realtime_members(struct call_queue *q)
02847 {
02848    struct ast_config *member_config = NULL;
02849    struct member *m;
02850    char *interface = NULL;
02851    struct ao2_iterator mem_iter;
02852 
02853    if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
02854       /* This queue doesn't have realtime members. If the queue still has any realtime
02855        * members in memory, they need to be removed.
02856        */
02857       ao2_lock(q);
02858       mem_iter = ao2_iterator_init(q->members, 0);
02859       while ((m = ao2_iterator_next(&mem_iter))) {
02860          if (m->realtime) {
02861             member_remove_from_queue(q, m);
02862          }
02863          ao2_ref(m, -1);
02864       }
02865       ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
02866       ao2_unlock(q);
02867       return;
02868    }
02869 
02870    ao2_lock(q);
02871 
02872    /* Temporarily set realtime  members dead so we can detect deleted ones.*/
02873    mem_iter = ao2_iterator_init(q->members, 0);
02874    while ((m = ao2_iterator_next(&mem_iter))) {
02875       if (m->realtime) {
02876          m->dead = 1;
02877       }
02878       ao2_ref(m, -1);
02879    }
02880    ao2_iterator_destroy(&mem_iter);
02881 
02882    while ((interface = ast_category_browse(member_config, interface))) {
02883       rt_handle_member_record(q, interface, member_config);
02884    }
02885 
02886    /* Delete all realtime members that have been deleted in DB. */
02887    mem_iter = ao2_iterator_init(q->members, 0);
02888    while ((m = ao2_iterator_next(&mem_iter))) {
02889       if (m->dead) {
02890          if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
02891             ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
02892          } else {
02893             ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
02894          }
02895          member_remove_from_queue(q, m);
02896       }
02897       ao2_ref(m, -1);
02898    }
02899    ao2_iterator_destroy(&mem_iter);
02900    ao2_unlock(q);
02901    ast_config_destroy(member_config);
02902 }
02903 
02904 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
02905 {
02906    struct call_queue *q;
02907    struct queue_ent *cur, *prev = NULL;
02908    int res = -1;
02909    int pos = 0;
02910    int inserted = 0;
02911 
02912    if (!(q = find_load_queue_rt_friendly(queuename))) {
02913       return res;
02914    }
02915    ao2_lock(q);
02916 
02917    /* This is our one */
02918    if (q->joinempty) {
02919       int status = 0;
02920       if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty))) {
02921          *reason = QUEUE_JOINEMPTY;
02922          ao2_unlock(q);
02923          queue_t_unref(q, "Done with realtime queue");
02924          return res;
02925       }
02926    }
02927    if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen)) {
02928       *reason = QUEUE_FULL;
02929    } else if (*reason == QUEUE_UNKNOWN) {
02930       /* There's space for us, put us at the right position inside
02931        * the queue.
02932        * Take into account the priority of the calling user */
02933       inserted = 0;
02934       prev = NULL;
02935       cur = q->head;
02936       while (cur) {
02937          /* We have higher priority than the current user, enter
02938           * before him, after all the other users with priority
02939           * higher or equal to our priority. */
02940          if ((!inserted) && (qe->prio > cur->prio)) {
02941             insert_entry(q, prev, qe, &pos);
02942             inserted = 1;
02943          }
02944          /* <= is necessary for the position comparison because it may not be possible to enter
02945           * at our desired position since higher-priority callers may have taken the position we want
02946           */
02947          if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
02948             insert_entry(q, prev, qe, &pos);
02949             inserted = 1;
02950             /*pos is incremented inside insert_entry, so don't need to add 1 here*/
02951             if (position < pos) {
02952                ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
02953             }
02954          }
02955          cur->pos = ++pos;
02956          prev = cur;
02957          cur = cur->next;
02958       }
02959       /* No luck, join at the end of the queue */
02960       if (!inserted) {
02961          insert_entry(q, prev, qe, &pos);
02962       }
02963       ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
02964       ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
02965       ast_copy_string(qe->context, q->context, sizeof(qe->context));
02966       q->count++;
02967       if (q->count == 1) {
02968          ast_devstate_changed(AST_DEVICE_RINGING, AST_DEVSTATE_CACHABLE, "Queue:%s", q->name);
02969       }
02970 
02971       res = 0;
02972       /*** DOCUMENTATION
02973       <managerEventInstance>
02974          <synopsis>Raised when a channel joins a Queue.</synopsis>
02975          <syntax>
02976             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
02977             <parameter name="Position">
02978                <para>This channel's current position in the queue.</para>
02979             </parameter>
02980             <parameter name="Count">
02981                <para>The total number of channels in the queue.</para>
02982             </parameter>
02983          </syntax>
02984          <see-also>
02985             <ref type="managerEvent">Leave</ref>
02986             <ref type="application">Queue</ref>
02987          </see-also>
02988       </managerEventInstance>
02989       ***/
02990       ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Join",
02991          "Channel: %s\r\n"
02992          "CallerIDNum: %s\r\n"
02993          "CallerIDName: %s\r\n"
02994          "ConnectedLineNum: %s\r\n"
02995          "ConnectedLineName: %s\r\n"
02996          "Queue: %s\r\n"
02997          "Position: %d\r\n"
02998          "Count: %d\r\n"
02999          "Uniqueid: %s\r\n",
03000          ast_channel_name(qe->chan),
03001          S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
03002          S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
03003          S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
03004          S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
03005          q->name, qe->pos, q->count, ast_channel_uniqueid(qe->chan));
03006       ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
03007    }
03008    ao2_unlock(q);
03009    queue_t_unref(q, "Done with realtime queue");
03010 
03011    return res;
03012 }
03013 
03014 static int play_file(struct ast_channel *chan, const char *filename)
03015 {
03016    int res;
03017 
03018    if (ast_strlen_zero(filename)) {
03019       return 0;
03020    }
03021 
03022    if (!ast_fileexists(filename, NULL, ast_channel_language(chan))) {
03023       return 0;
03024    }
03025 
03026    ast_stopstream(chan);
03027 
03028    res = ast_streamfile(chan, filename, ast_channel_language(chan));
03029    if (!res) {
03030       res = ast_waitstream(chan, AST_DIGIT_ANY);
03031    }
03032 
03033    ast_stopstream(chan);
03034 
03035    return res;
03036 }
03037 
03038 /*!
03039  * \brief Check for valid exit from queue via goto
03040  * \retval 0 if failure
03041  * \retval 1 if successful
03042 */
03043 static int valid_exit(struct queue_ent *qe, char digit)
03044 {
03045    int digitlen = strlen(qe->digits);
03046 
03047    /* Prevent possible buffer overflow */
03048    if (digitlen < sizeof(qe->digits) - 2) {
03049       qe->digits[digitlen] = digit;
03050       qe->digits[digitlen + 1] = '\0';
03051    } else {
03052       qe->digits[0] = '\0';
03053       return 0;
03054    }
03055 
03056    /* If there's no context to goto, short-circuit */
03057    if (ast_strlen_zero(qe->context)) {
03058       return 0;
03059    }
03060 
03061    /* If the extension is bad, then reset the digits to blank */
03062    if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
03063       S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, NULL))) {
03064       qe->digits[0] = '\0';
03065       return 0;
03066    }
03067 
03068    /* We have an exact match */
03069    if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
03070       qe->valid_digits = 1;
03071       /* Return 1 on a successful goto */
03072       return 1;
03073    }
03074 
03075    return 0;
03076 }
03077 
03078 static int say_position(struct queue_ent *qe, int ringing)
03079 {
03080    int res = 0, avgholdmins, avgholdsecs, announceposition = 0;
03081    int say_thanks = 1;
03082    time_t now;
03083 
03084    /* Let minannouncefrequency seconds pass between the start of each position announcement */
03085    time(&now);
03086    if ((now - qe->last_pos) < qe->parent->minannouncefrequency) {
03087       return 0;
03088    }
03089 
03090    /* If either our position has changed, or we are over the freq timer, say position */
03091    if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency)) {
03092       return 0;
03093    }
03094 
03095    if (ringing) {
03096       ast_indicate(qe->chan,-1);
03097    } else {
03098       ast_moh_stop(qe->chan);
03099    }
03100 
03101    if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
03102       qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
03103       (qe->parent->announceposition == ANNOUNCEPOSITION_LIMIT &&
03104       qe->pos <= qe->parent->announcepositionlimit)) {
03105          announceposition = 1;
03106    }
03107 
03108 
03109    if (announceposition == 1) {
03110       /* Say we're next, if we are */
03111       if (qe->pos == 1) {
03112          res = play_file(qe->chan, qe->parent->sound_next);
03113          if (res) {
03114             goto playout;
03115          }
03116          goto posout;
03117       } else {
03118          if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
03119             /* More than Case*/
03120             res = play_file(qe->chan, qe->parent->queue_quantity1);
03121             if (res) {
03122                goto playout;
03123             }
03124             res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */
03125             if (res) {
03126                goto playout;
03127             }
03128          } else {
03129             /* Normal Case */
03130             res = play_file(qe->chan, qe->parent->sound_thereare);
03131             if (res) {
03132                goto playout;
03133             }
03134             res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */
03135             if (res) {
03136                goto playout;
03137             }
03138          }
03139          if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
03140             /* More than Case*/
03141             res = play_file(qe->chan, qe->parent->queue_quantity2);
03142             if (res) {
03143                goto playout;
03144             }
03145          } else {
03146             res = play_file(qe->chan, qe->parent->sound_calls);
03147             if (res) {
03148                goto playout;
03149             }
03150          }
03151       }
03152    }
03153    /* Round hold time to nearest minute */
03154    avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
03155 
03156    /* If they have specified a rounding then round the seconds as well */
03157    if (qe->parent->roundingseconds) {
03158       avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
03159       avgholdsecs *= qe->parent->roundingseconds;
03160    } else {
03161       avgholdsecs = 0;
03162    }
03163 
03164    ast_verb(3, "Hold time for %s is %d minute(s) %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
03165 
03166    /* If the hold time is >1 min, if it's enabled, and if it's not
03167       supposed to be only once and we have already said it, say it */
03168     if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
03169         ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
03170         !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
03171       res = play_file(qe->chan, qe->parent->sound_holdtime);
03172       if (res) {
03173          goto playout;
03174       }
03175 
03176       if (avgholdmins >= 1) {
03177          res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
03178          if (res) {
03179             goto playout;
03180          }
03181 
03182          if (avgholdmins == 1) {
03183             res = play_file(qe->chan, qe->parent->sound_minute);
03184             if (res) {
03185                goto playout;
03186             }
03187          } else {
03188             res = play_file(qe->chan, qe->parent->sound_minutes);
03189             if (res) {
03190                goto playout;
03191             }
03192          }
03193       }
03194       if (avgholdsecs >= 1) {
03195          res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
03196          if (res) {
03197             goto playout;
03198          }
03199 
03200          res = play_file(qe->chan, qe->parent->sound_seconds);
03201          if (res) {
03202             goto playout;
03203          }
03204       }
03205    } else if (qe->parent->announceholdtime && !qe->parent->announceposition) {
03206       say_thanks = 0;
03207    }
03208 
03209 posout:
03210    if (qe->parent->announceposition) {
03211       ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
03212          ast_channel_name(qe->chan), qe->parent->name, qe->pos);
03213    }
03214    if (say_thanks) {
03215       res = play_file(qe->chan, qe->parent->sound_thanks);
03216    }
03217 playout:
03218 
03219    if ((res > 0 && !valid_exit(qe, res))) {
03220       res = 0;
03221    }
03222 
03223    /* Set our last_pos indicators */
03224    qe->last_pos = now;
03225    qe->last_pos_said = qe->pos;
03226 
03227    /* Don't restart music on hold if we're about to exit the caller from the queue */
03228    if (!res) {
03229       if (ringing) {
03230          ast_indicate(qe->chan, AST_CONTROL_RINGING);
03231       } else {
03232          ast_moh_start(qe->chan, qe->moh, NULL);
03233       }
03234    }
03235    return res;
03236 }
03237 
03238 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
03239 {
03240    int oldvalue;
03241 
03242    /* Calculate holdtime using an exponential average */
03243    /* Thanks to SRT for this contribution */
03244    /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */
03245 
03246    ao2_lock(qe->parent);
03247    oldvalue = qe->parent->holdtime;
03248    qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
03249    ao2_unlock(qe->parent);
03250 }
03251 
03252 /*! \brief Caller leaving queue.
03253  *
03254  * Search the queue to find the leaving client, if found remove from queue
03255  * create manager event, move others up the queue.
03256 */
03257 static void leave_queue(struct queue_ent *qe)
03258 {
03259    struct call_queue *q;
03260    struct queue_ent *current, *prev = NULL;
03261    struct penalty_rule *pr_iter;
03262    int pos = 0;
03263 
03264    if (!(q = qe->parent)) {
03265       return;
03266    }
03267    queue_t_ref(q, "Copy queue pointer from queue entry");
03268    ao2_lock(q);
03269 
03270    prev = NULL;
03271    for (current = q->head; current; current = current->next) {
03272       if (current == qe) {
03273          char posstr[20];
03274          q->count--;
03275          if (!q->count) {
03276             ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s", q->name);
03277          }
03278 
03279          /* Take us out of the queue */
03280          /*** DOCUMENTATION
03281          <managerEventInstance>
03282             <synopsis>Raised when a channel leaves a Queue.</synopsis>
03283             <syntax>
03284                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
03285                <xi:include xpointer="xpointer(/docs/managerEvent[@name='Join']/managerEventInstance/syntax/parameter[@name='Count'])" />
03286                <xi:include xpointer="xpointer(/docs/managerEvent[@name='Join']/managerEventInstance/syntax/parameter[@name='Position'])" />
03287             </syntax>
03288             <see-also>
03289                <ref type="managerEvent">Join</ref>
03290             </see-also>
03291          </managerEventInstance>
03292          ***/
03293          ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Leave",
03294             "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
03295             ast_channel_name(qe->chan), q->name,  q->count, qe->pos, ast_channel_uniqueid(qe->chan));
03296          ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
03297          /* Take us out of the queue */
03298          if (prev) {
03299             prev->next = current->next;
03300          } else {
03301             q->head = current->next;
03302          }
03303          /* Free penalty rules */
03304          while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list))) {
03305             ast_free(pr_iter);
03306          }
03307          snprintf(posstr, sizeof(posstr), "%d", qe->pos);
03308          pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
03309       } else {
03310          /* Renumber the people after us in the queue based on a new count */
03311          current->pos = ++pos;
03312          prev = current;
03313       }
03314    }
03315    ao2_unlock(q);
03316 
03317    /*If the queue is a realtime queue, check to see if it's still defined in real time*/
03318    if (q->realtime) {
03319       struct ast_variable *var;
03320       if (!(var = ast_load_realtime("queues", "name", q->name, SENTINEL))) {
03321          q->dead = 1;
03322       } else {
03323          ast_variables_destroy(var);
03324       }
03325    }
03326 
03327    if (q->dead) {
03328       /* It's dead and nobody is in it, so kill it */
03329       queues_t_unlink(queues, q, "Queue is now dead; remove it from the container");
03330    }
03331    /* unref the explicit ref earlier in the function */
03332    queue_t_unref(q, "Expire copied reference");
03333 }
03334 
03335 /*!
03336  * \internal
03337  * \brief Destroy the given callattempt structure and free it.
03338  * \since 1.8
03339  *
03340  * \param doomed callattempt structure to destroy.
03341  *
03342  * \return Nothing
03343  */
03344 static void callattempt_free(struct callattempt *doomed)
03345 {
03346    if (doomed->member) {
03347       ao2_ref(doomed->member, -1);
03348    }
03349    ast_party_connected_line_free(&doomed->connected);
03350    ast_free(doomed);
03351 }
03352 
03353 /*! \brief Hang up a list of outgoing calls */
03354 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
03355 {
03356    struct callattempt *oo;
03357 
03358    while (outgoing) {
03359       /* If someone else answered the call we should indicate this in the CANCEL */
03360       /* Hangup any existing lines we have open */
03361       if (outgoing->chan && (outgoing->chan != exception)) {
03362          if (exception || cancel_answered_elsewhere) {
03363             ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
03364          }
03365          ast_hangup(outgoing->chan);
03366       }
03367       oo = outgoing;
03368       outgoing = outgoing->q_next;
03369       ast_aoc_destroy_decoded(oo->aoc_s_rate_list);
03370       callattempt_free(oo);
03371    }
03372 }
03373 
03374 /*!
03375  * \brief Get the number of members available to accept a call.
03376  *
03377  * \note The queue passed in should be locked prior to this function call
03378  *
03379  * \param[in] q The queue for which we are couting the number of available members
03380  * \return Return the number of available members in queue q
03381  */
03382 static int num_available_members(struct call_queue *q)
03383 {
03384    struct member *mem;
03385    int avl = 0;
03386    struct ao2_iterator mem_iter;
03387 
03388    mem_iter = ao2_iterator_init(q->members, 0);
03389    while ((mem = ao2_iterator_next(&mem_iter))) {
03390 
03391       avl += is_member_available(q, mem);
03392       ao2_ref(mem, -1);
03393 
03394       /* If autofill is not enabled or if the queue's strategy is ringall, then
03395        * we really don't care about the number of available members so much as we
03396        * do that there is at least one available.
03397        *
03398        * In fact, we purposely will return from this function stating that only
03399        * one member is available if either of those conditions hold. That way,
03400        * functions which determine what action to take based on the number of available
03401        * members will operate properly. The reasoning is that even if multiple
03402        * members are available, only the head caller can actually be serviced.
03403        */
03404       if ((!q->autofill || q->strategy == QUEUE_STRATEGY_RINGALL) && avl) {
03405          break;
03406       }
03407    }
03408    ao2_iterator_destroy(&mem_iter);
03409 
03410    return avl;
03411 }
03412 
03413 /* traverse all defined queues which have calls waiting and contain this member
03414    return 0 if no other queue has precedence (higher weight) or 1 if found  */
03415 static int compare_weight(struct call_queue *rq, struct member *member)
03416 {
03417    struct call_queue *q;
03418    struct member *mem;
03419    int found = 0;
03420    struct ao2_iterator queue_iter;
03421 
03422    queue_iter = ao2_iterator_init(queues, 0);
03423    while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
03424       if (q == rq) { /* don't check myself, could deadlock */
03425          queue_t_unref(q, "Done with iterator");
03426          continue;
03427       }
03428       ao2_lock(q);
03429       if (q->count && q->members) {
03430          if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
03431             ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
03432             if (q->weight > rq->weight && q->count >= num_available_members(q)) {
03433                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);
03434                found = 1;
03435             }
03436             ao2_ref(mem, -1);
03437          }
03438       }
03439       ao2_unlock(q);
03440       queue_t_unref(q, "Done with iterator");
03441       if (found) {
03442          break;
03443       }
03444    }
03445    ao2_iterator_destroy(&queue_iter);
03446    return found;
03447 }
03448 
03449 /*! \brief common hangup actions */
03450 static void do_hang(struct callattempt *o)
03451 {
03452    o->stillgoing = 0;
03453    ast_hangup(o->chan);
03454    o->chan = NULL;
03455 }
03456 
03457 /*! \brief convert "\n" to "\nVariable: " ready for manager to use */
03458 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
03459 {
03460    struct ast_str *buf = ast_str_thread_get(&ast_str_thread_global_buf, len + 1);
03461    const char *tmp;
03462 
03463    if (pbx_builtin_serialize_variables(chan, &buf)) {
03464       int i, j;
03465 
03466       /* convert "\n" to "\nVariable: " */
03467       strcpy(vars, "Variable: ");
03468       tmp = ast_str_buffer(buf);
03469 
03470       for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
03471          vars[j] = tmp[i];
03472 
03473          if (tmp[i + 1] == '\0') {
03474             break;
03475          }
03476          if (tmp[i] == '\n') {
03477             vars[j++] = '\r';
03478             vars[j++] = '\n';
03479 
03480             ast_copy_string(&(vars[j]), "Variable: ", len - j);
03481             j += 9;
03482          }
03483       }
03484       if (j > len - 3) {
03485          j = len - 3;
03486       }
03487       vars[j++] = '\r';
03488       vars[j++] = '\n';
03489       vars[j] = '\0';
03490    } else {
03491       /* there are no channel variables; leave it blank */
03492       *vars = '\0';
03493    }
03494    return vars;
03495 }
03496 
03497 /*!
03498  * \internal
03499  * \brief Check if the member status is available.
03500  *
03501  * \param status Member status to check if available.
03502  *
03503  * \retval non-zero if the member status is available.
03504  */
03505 static int member_status_available(int status)
03506 {
03507    return status == AST_DEVICE_NOT_INUSE || status == AST_DEVICE_UNKNOWN;
03508 }
03509 
03510 /*!
03511  * \internal
03512  * \brief Clear the member call pending flag.
03513  *
03514  * \param mem Queue member.
03515  *
03516  * \return Nothing
03517  */
03518 static void member_call_pending_clear(struct member *mem)
03519 {
03520    ao2_lock(mem);
03521    mem->call_pending = 0;
03522    ao2_unlock(mem);
03523 }
03524 
03525 /*!
03526  * \internal
03527  * \brief Set the member call pending flag.
03528  *
03529  * \param mem Queue member.
03530  *
03531  * \retval non-zero if call pending flag was already set.
03532  */
03533 static int member_call_pending_set(struct member *mem)
03534 {
03535    int old_pending;
03536 
03537    ao2_lock(mem);
03538    old_pending = mem->call_pending;
03539    mem->call_pending = 1;
03540    ao2_unlock(mem);
03541 
03542    return old_pending;
03543 }
03544 
03545 /*!
03546  * \internal
03547  * \brief Determine if can ring a queue entry.
03548  *
03549  * \param qe Queue entry to check.
03550  * \param call Member call attempt.
03551  *
03552  * \retval non-zero if an entry can be called.
03553  */
03554 static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
03555 {
03556    if (call->member->paused) {
03557       ast_debug(1, "%s paused, can't receive call\n", call->interface);
03558       return 0;
03559    }
03560 
03561    if (!call->member->ringinuse && !member_status_available(call->member->status)) {
03562       ast_debug(1, "%s not available, can't receive call\n", call->interface);
03563       return 0;
03564    }
03565 
03566    if ((call->lastqueue && call->lastqueue->wrapuptime && (time(NULL) - call->lastcall < call->lastqueue->wrapuptime))
03567       || (!call->lastqueue && qe->parent->wrapuptime && (time(NULL) - call->lastcall < qe->parent->wrapuptime))) {
03568       ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
03569          (call->lastqueue ? call->lastqueue->name : qe->parent->name),
03570          call->interface);
03571       return 0;
03572    }
03573 
03574    if (use_weight && compare_weight(qe->parent, call->member)) {
03575       ast_debug(1, "Priority queue delaying call to %s:%s\n",
03576          qe->parent->name, call->interface);
03577       return 0;
03578    }
03579 
03580    if (!call->member->ringinuse) {
03581       if (member_call_pending_set(call->member)) {
03582          ast_debug(1, "%s has another call pending, can't receive call\n",
03583             call->interface);
03584          return 0;
03585       }
03586 
03587       /*
03588        * The queue member is available.  Get current status to be sure
03589        * because the device state and extension state callbacks may
03590        * not have updated the status yet.
03591        */
03592       if (!member_status_available(get_queue_member_status(call->member))) {
03593          ast_debug(1, "%s actually not available, can't receive call\n",
03594             call->interface);
03595          member_call_pending_clear(call->member);
03596          return 0;
03597       }
03598    }
03599 
03600    return 1;
03601 }
03602 
03603 /*!
03604  * \brief Part 2 of ring_one
03605  *
03606  * Does error checking before attempting to request a channel and call a member.
03607  * This function is only called from ring_one().
03608  * Failure can occur if:
03609  * - Agent on call
03610  * - Agent is paused
03611  * - Wrapup time not expired
03612  * - Priority by another queue
03613  *
03614  * \retval 1 on success to reach a free agent
03615  * \retval 0 on failure to get agent.
03616  */
03617 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
03618 {
03619    int res;
03620    int status;
03621    char tech[256];
03622    char *location;
03623    const char *macrocontext, *macroexten;
03624 
03625    /* on entry here, we know that tmp->chan == NULL */
03626    if (!can_ring_entry(qe, tmp)) {
03627       if (ast_channel_cdr(qe->chan)) {
03628          ast_cdr_busy(ast_channel_cdr(qe->chan));
03629       }
03630       tmp->stillgoing = 0;
03631       ++*busies;
03632       return 0;
03633    }
03634    ast_assert(tmp->member->ringinuse || tmp->member->call_pending);
03635 
03636    ast_copy_string(tech, tmp->interface, sizeof(tech));
03637    if ((location = strchr(tech, '/'))) {
03638       *location++ = '\0';
03639    } else {
03640       location = "";
03641    }
03642 
03643    /* Request the peer */
03644    tmp->chan = ast_request(tech, ast_channel_nativeformats(qe->chan), qe->chan, location, &status);
03645    if (!tmp->chan) {       /* If we can't, just go on to the next call */
03646       ao2_lock(qe->parent);
03647       qe->parent->rrpos++;
03648       qe->linpos++;
03649       ao2_unlock(qe->parent);
03650 
03651       member_call_pending_clear(tmp->member);
03652 
03653       if (ast_channel_cdr(qe->chan)) {
03654          ast_cdr_busy(ast_channel_cdr(qe->chan));
03655       }
03656       tmp->stillgoing = 0;
03657       ++*busies;
03658       return 0;
03659    }
03660 
03661    ast_channel_lock_both(tmp->chan, qe->chan);
03662 
03663    if (qe->cancel_answered_elsewhere) {
03664       ast_channel_hangupcause_set(tmp->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
03665    }
03666    ast_channel_appl_set(tmp->chan, "AppQueue");
03667    ast_channel_data_set(tmp->chan, "(Outgoing Line)");
03668    memset(ast_channel_whentohangup(tmp->chan), 0, sizeof(*ast_channel_whentohangup(tmp->chan)));
03669 
03670    /* If the new channel has no callerid, try to guess what it should be */
03671    if (!ast_channel_caller(tmp->chan)->id.number.valid) {
03672       if (ast_channel_connected(qe->chan)->id.number.valid) {
03673          struct ast_party_caller caller;
03674 
03675          ast_party_caller_set_init(&caller, ast_channel_caller(tmp->chan));
03676          caller.id = ast_channel_connected(qe->chan)->id;
03677          caller.ani = ast_channel_connected(qe->chan)->ani;
03678          ast_channel_set_caller_event(tmp->chan, &caller, NULL);
03679       } else if (!ast_strlen_zero(ast_channel_dialed(qe->chan)->number.str)) {
03680          ast_set_callerid(tmp->chan, ast_channel_dialed(qe->chan)->number.str, NULL, NULL);
03681       } else if (!ast_strlen_zero(S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)))) {
03682          ast_set_callerid(tmp->chan, S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)), NULL, NULL);
03683       }
03684       tmp->dial_callerid_absent = 1;
03685    }
03686 
03687    ast_party_redirecting_copy(ast_channel_redirecting(tmp->chan), ast_channel_redirecting(qe->chan));
03688 
03689    ast_channel_dialed(tmp->chan)->transit_network_select = ast_channel_dialed(qe->chan)->transit_network_select;
03690 
03691    ast_connected_line_copy_from_caller(ast_channel_connected(tmp->chan), ast_channel_caller(qe->chan));
03692 
03693    /* Inherit specially named variables from parent channel */
03694    ast_channel_inherit_variables(qe->chan, tmp->chan);
03695    ast_channel_datastore_inherit(qe->chan, tmp->chan);
03696 
03697    /* Presense of ADSI CPE on outgoing channel follows ours */
03698    ast_channel_adsicpe_set(tmp->chan, ast_channel_adsicpe(qe->chan));
03699 
03700    /* Inherit context and extension */
03701    macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
03702    ast_channel_dialcontext_set(tmp->chan, ast_strlen_zero(macrocontext) ? ast_channel_context(qe->chan) : macrocontext);
03703    macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
03704    if (!ast_strlen_zero(macroexten)) {
03705       ast_channel_exten_set(tmp->chan, macroexten);
03706    } else {
03707       ast_channel_exten_set(tmp->chan, ast_channel_exten(qe->chan));
03708    }
03709    if (ast_cdr_isset_unanswered()) {
03710       /* they want to see the unanswered dial attempts! */
03711       /* set up the CDR fields on all the CDRs to give sensical information */
03712       ast_cdr_setdestchan(ast_channel_cdr(tmp->chan), ast_channel_name(tmp->chan));
03713       strcpy(ast_channel_cdr(tmp->chan)->clid, ast_channel_cdr(qe->chan)->clid);
03714       strcpy(ast_channel_cdr(tmp->chan)->channel, ast_channel_cdr(qe->chan)->channel);
03715       strcpy(ast_channel_cdr(tmp->chan)->src, ast_channel_cdr(qe->chan)->src);
03716       strcpy(ast_channel_cdr(tmp->chan)->dst, ast_channel_exten(qe->chan));
03717       strcpy(ast_channel_cdr(tmp->chan)->dcontext, ast_channel_context(qe->chan));
03718       strcpy(ast_channel_cdr(tmp->chan)->lastapp, ast_channel_cdr(qe->chan)->lastapp);
03719       strcpy(ast_channel_cdr(tmp->chan)->lastdata, ast_channel_cdr(qe->chan)->lastdata);
03720       ast_channel_cdr(tmp->chan)->amaflags = ast_channel_cdr(qe->chan)->amaflags;
03721       strcpy(ast_channel_cdr(tmp->chan)->accountcode, ast_channel_cdr(qe->chan)->accountcode);
03722       strcpy(ast_channel_cdr(tmp->chan)->userfield, ast_channel_cdr(qe->chan)->userfield);
03723    }
03724 
03725    ast_channel_unlock(tmp->chan);
03726    ast_channel_unlock(qe->chan);
03727 
03728    /* Place the call, but don't wait on the answer */
03729    if ((res = ast_call(tmp->chan, location, 0))) {
03730       /* Again, keep going even if there's an error */
03731       ast_verb(3, "Couldn't call %s\n", tmp->interface);
03732       do_hang(tmp);
03733       member_call_pending_clear(tmp->member);
03734       ++*busies;
03735       return 0;
03736    }
03737 
03738    if (qe->parent->eventwhencalled) {
03739       char vars[2048];
03740 
03741       ast_channel_lock_both(tmp->chan, qe->chan);
03742 
03743       /*** DOCUMENTATION
03744       <managerEventInstance>
03745          <synopsis>Raised when an Agent is notified of a member in the queue.</synopsis>
03746          <syntax>
03747             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
03748             <parameter name="AgentCalled">
03749                <para>The agent's technology or location.</para>
03750             </parameter>
03751             <parameter name="AgentName">
03752                <para>The name of the agent.</para>
03753             </parameter>
03754             <parameter name="Variable" required="no" multiple="yes">
03755                <para>Optional channel variables from the ChannelCalling channel</para>
03756             </parameter>
03757          </syntax>
03758          <see-also>
03759             <ref type="managerEvent">AgentRingNoAnswer</ref>
03760             <ref type="managerEvent">AgentComplete</ref>
03761             <ref type="managerEvent">AgentConnect</ref>
03762          </see-also>
03763       </managerEventInstance>
03764       ***/
03765       manager_event(EVENT_FLAG_AGENT, "AgentCalled",
03766          "Queue: %s\r\n"
03767          "AgentCalled: %s\r\n"
03768          "AgentName: %s\r\n"
03769          "ChannelCalling: %s\r\n"
03770          "DestinationChannel: %s\r\n"
03771          "CallerIDNum: %s\r\n"
03772          "CallerIDName: %s\r\n"
03773          "ConnectedLineNum: %s\r\n"
03774          "ConnectedLineName: %s\r\n"
03775          "Context: %s\r\n"
03776          "Extension: %s\r\n"
03777          "Priority: %d\r\n"
03778          "Uniqueid: %s\r\n"
03779          "%s",
03780          qe->parent->name, tmp->interface, tmp->member->membername, ast_channel_name(qe->chan), ast_channel_name(tmp->chan),
03781          S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),
03782          S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
03783          S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),
03784          S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
03785          ast_channel_context(qe->chan), ast_channel_exten(qe->chan), ast_channel_priority(qe->chan), ast_channel_uniqueid(qe->chan),
03786          qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
03787 
03788       ast_channel_unlock(tmp->chan);
03789       ast_channel_unlock(qe->chan);
03790 
03791       ast_verb(3, "Called %s\n", tmp->interface);
03792    }
03793 
03794    member_call_pending_clear(tmp->member);
03795    return 1;
03796 }
03797 
03798 /*! \brief find the entry with the best metric, or NULL */
03799 static struct callattempt *find_best(struct callattempt *outgoing)
03800 {
03801    struct callattempt *best = NULL, *cur;
03802 
03803    for (cur = outgoing; cur; cur = cur->q_next) {
03804       if (cur->stillgoing &&              /* Not already done */
03805          !cur->chan &&              /* Isn't already going */
03806          (!best || cur->metric < best->metric)) {     /* We haven't found one yet, or it's better */
03807          best = cur;
03808       }
03809    }
03810 
03811    return best;
03812 }
03813 
03814 /*!
03815  * \brief Place a call to a queue member.
03816  *
03817  * Once metrics have been calculated for each member, this function is used
03818  * to place a call to the appropriate member (or members). The low-level
03819  * channel-handling and error detection is handled in ring_entry
03820  *
03821  * \retval 1 if a member was called successfully
03822  * \retval 0 otherwise
03823  */
03824 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
03825 {
03826    int ret = 0;
03827 
03828    while (ret == 0) {
03829       struct callattempt *best = find_best(outgoing);
03830       if (!best) {
03831          ast_debug(1, "Nobody left to try ringing in queue\n");
03832          break;
03833       }
03834       if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
03835          struct callattempt *cur;
03836          /* Ring everyone who shares this best metric (for ringall) */
03837          for (cur = outgoing; cur; cur = cur->q_next) {
03838             if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
03839                ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
03840                ret |= ring_entry(qe, cur, busies);
03841             }
03842          }
03843       } else {
03844          /* Ring just the best channel */
03845          ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
03846          ret = ring_entry(qe, best, busies);
03847       }
03848 
03849       /* If we have timed out, break out */
03850       if (qe->expire && (time(NULL) >= qe->expire)) {
03851          ast_debug(1, "Queue timed out while ringing members.\n");
03852          ret = 0;
03853          break;
03854       }
03855    }
03856 
03857    return ret;
03858 }
03859 
03860 /*! \brief Search for best metric and add to Round Robbin queue */
03861 static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
03862 {
03863    struct callattempt *best = find_best(outgoing);
03864 
03865    if (best) {
03866       /* Ring just the best channel */
03867       ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
03868       qe->parent->rrpos = best->metric % 1000;
03869    } else {
03870       /* Just increment rrpos */
03871       if (qe->parent->wrapped) {
03872          /* No more channels, start over */
03873          qe->parent->rrpos = 0;
03874       } else {
03875          /* Prioritize next entry */
03876          qe->parent->rrpos++;
03877       }
03878    }
03879    qe->parent->wrapped = 0;
03880 
03881    return 0;
03882 }
03883 
03884 /*! \brief Search for best metric and add to Linear queue */
03885 static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
03886 {
03887    struct callattempt *best = find_best(outgoing);
03888 
03889    if (best) {
03890       /* Ring just the best channel */
03891       ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
03892       qe->linpos = best->metric % 1000;
03893    } else {
03894       /* Just increment rrpos */
03895       if (qe->linwrapped) {
03896          /* No more channels, start over */
03897          qe->linpos = 0;
03898       } else {
03899          /* Prioritize next entry */
03900          qe->linpos++;
03901       }
03902    }
03903    qe->linwrapped = 0;
03904 
03905    return 0;
03906 }
03907 
03908 /*! \brief Playback announcement to queued members if period has elapsed */
03909 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
03910 {
03911    int res = 0;
03912    time_t now;
03913 
03914    /* Get the current time */
03915    time(&now);
03916 
03917    /* Check to see if it is time to announce */
03918    if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency) {
03919       return 0;
03920    }
03921 
03922    /* Stop the music on hold so we can play our own file */
03923    if (ringing) {
03924       ast_indicate(qe->chan,-1);
03925    } else {
03926       ast_moh_stop(qe->chan);
03927    }
03928 
03929    ast_verb(3, "Playing periodic announcement\n");
03930 
03931    if (qe->parent->randomperiodicannounce && qe->parent->numperiodicannounce) {
03932       qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
03933    } else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce ||
03934       ast_str_strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]) == 0) {
03935       qe->last_periodic_announce_sound = 0;
03936    }
03937 
03938    /* play the announcement */
03939    res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]));
03940 
03941    if (res > 0 && !valid_exit(qe, res)) {
03942       res = 0;
03943    }
03944 
03945    /* Resume Music on Hold if the caller is going to stay in the queue */
03946    if (!res) {
03947       if (ringing) {
03948          ast_indicate(qe->chan, AST_CONTROL_RINGING);
03949       } else {
03950          ast_moh_start(qe->chan, qe->moh, NULL);
03951       }
03952    }
03953 
03954    /* update last_periodic_announce_time */
03955    if (qe->parent->relativeperiodicannounce) {
03956       time(&qe->last_periodic_announce_time);
03957    } else {
03958       qe->last_periodic_announce_time = now;
03959    }
03960 
03961    /* Update the current periodic announcement to the next announcement */
03962    if (!qe->parent->randomperiodicannounce) {
03963       qe->last_periodic_announce_sound++;
03964    }
03965 
03966    return res;
03967 }
03968 
03969 /*! \brief Record that a caller gave up on waiting in queue */
03970 static void record_abandoned(struct queue_ent *qe)
03971 {
03972    set_queue_variables(qe->parent, qe->chan);
03973    ao2_lock(qe->parent);
03974    /*** DOCUMENTATION
03975    <managerEventInstance>
03976       <synopsis>Raised when an caller abandons the queue.</synopsis>
03977       <syntax>
03978          <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
03979          <xi:include xpointer="xpointer(/docs/managerEvent[@name='Join']/managerEventInstance/syntax/parameter[@name='Position'])" />
03980          <parameter name="OriginalPosition">
03981             <para>The channel's original position in the queue.</para>
03982          </parameter>
03983          <parameter name="HoldTime">
03984             <para>The time the channel was in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
03985          </parameter>
03986       </syntax>
03987    </managerEventInstance>
03988    ***/
03989    manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
03990       "Queue: %s\r\n"
03991       "Uniqueid: %s\r\n"
03992       "Position: %d\r\n"
03993       "OriginalPosition: %d\r\n"
03994       "HoldTime: %d\r\n",
03995       qe->parent->name, ast_channel_uniqueid(qe->chan), qe->pos, qe->opos, (int)(time(NULL) - qe->start));
03996 
03997    qe->parent->callsabandoned++;
03998    ao2_unlock(qe->parent);
03999 }
04000 
04001 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
04002 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int autopause)
04003 {
04004    ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
04005 
04006    /* Stop ringing, and resume MOH if specified */
04007    if (qe->ring_when_ringing) {
04008       ast_indicate(qe->chan, -1);
04009       ast_moh_start(qe->chan, qe->moh, NULL);
04010    }
04011 
04012    if (qe->parent->eventwhencalled) {
04013       char vars[2048];
04014       /*** DOCUMENTATION
04015       <managerEventInstance>
04016          <synopsis>Raised when an agent is notified of a member in the queue and fails to answer.</synopsis>
04017          <syntax>
04018             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
04019             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
04020             <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentCalled']/managerEventInstance/syntax/parameter[@name='Variable'])" />
04021             <parameter name="Member">
04022                <para>The queue member's channel technology or location.</para>
04023             </parameter>
04024             <parameter name="RingTime">
04025                <para>The time the agent was rung, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
04026             </parameter>
04027          </syntax>
04028          <see-also>
04029             <ref type="managerEvent">AgentCalled</ref>
04030          </see-also>
04031       </managerEventInstance>
04032       ***/
04033       manager_event(EVENT_FLAG_AGENT, "AgentRingNoAnswer",
04034                   "Queue: %s\r\n"
04035                   "Uniqueid: %s\r\n"
04036                   "Channel: %s\r\n"
04037                   "Member: %s\r\n"
04038                   "MemberName: %s\r\n"
04039                   "RingTime: %d\r\n"
04040                   "%s",
04041                   qe->parent->name,
04042                   ast_channel_uniqueid(qe->chan),
04043                   ast_channel_name(qe->chan),
04044                   interface,
04045                   membername,
04046                   rnatime,
04047                   qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
04048    }
04049    ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), membername, "RINGNOANSWER", "%d", rnatime);
04050    if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && autopause) {
04051       if (qe->parent->autopausedelay > 0) {
04052          struct member *mem;
04053          ao2_lock(qe->parent);
04054          if ((mem = interface_exists(qe->parent, interface))) {
04055             time_t idletime = time(&idletime)-mem->lastcall;
04056             if ((mem->lastcall != 0) && (qe->parent->autopausedelay > idletime)) {
04057                ao2_unlock(qe->parent);
04058                ao2_ref(mem, -1);
04059                return;
04060             }
04061             ao2_ref(mem, -1);
04062          }
04063          ao2_unlock(qe->parent);
04064       }
04065       if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
04066          if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
04067             ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
04068                interface, qe->parent->name);
04069          } else {
04070             ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
04071          }
04072       } else {
04073          /* If queue autopause is mode all, just don't send any queue to stop.
04074          * the function will stop in all queues */
04075          if (!set_member_paused("", interface, "Auto-Pause", 1)) {
04076             ast_verb(3, "Auto-Pausing Queue Member %s in all queues since they failed to answer on queue %s.\n",
04077                   interface, qe->parent->name);
04078          } else {
04079                ast_verb(3, "Failed to pause Queue Member %s in all queues!\n", interface);
04080          }
04081       }
04082    }
04083    return;
04084 }
04085 
04086 #define AST_MAX_WATCHERS 256
04087 /*!
04088  * \brief Wait for a member to answer the call
04089  *
04090  * \param[in] qe the queue_ent corresponding to the caller in the queue
04091  * \param[in] outgoing the list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
04092  * \param[in] to the amount of time (in milliseconds) to wait for a response
04093  * \param[out] digit if a user presses a digit to exit the queue, this is the digit the caller pressed
04094  * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
04095  * \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
04096  * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
04097  *
04098  * \todo eventually all call forward logic should be intergerated into and replaced by ast_call_forward()
04099  */
04100 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)
04101 {
04102    const char *queue = qe->parent->name;
04103    struct callattempt *o, *start = NULL, *prev = NULL;
04104    int status;
04105    int numbusies = prebusies;
04106    int numnochan = 0;
04107    int stillgoing = 0;
04108    int orig = *to;
04109    struct ast_frame *f;
04110    struct callattempt *peer = NULL;
04111    struct ast_channel *winner;
04112    struct ast_channel *in = qe->chan;
04113    char on[80] = "";
04114    char membername[80] = "";
04115    long starttime = 0;
04116    long endtime = 0;
04117 #ifdef HAVE_EPOLL
04118    struct callattempt *epollo;
04119 #endif
04120    struct ast_party_connected_line connected_caller;
04121    char *inchan_name;
04122    struct timeval start_time_tv = ast_tvnow();
04123 
04124    ast_party_connected_line_init(&connected_caller);
04125 
04126    ast_channel_lock(qe->chan);
04127    inchan_name = ast_strdupa(ast_channel_name(qe->chan));
04128    ast_channel_unlock(qe->chan);
04129 
04130    starttime = (long) time(NULL);
04131 #ifdef HAVE_EPOLL
04132    for (epollo = outgoing; epollo; epollo = epollo->q_next) {
04133       if (epollo->chan) {
04134          ast_poll_channel_add(in, epollo->chan);
04135       }
04136    }
04137 #endif
04138 
04139    while ((*to = ast_remaining_ms(start_time_tv, orig)) && !peer) {
04140       int numlines, retry, pos = 1;
04141       struct ast_channel *watchers[AST_MAX_WATCHERS];
04142       watchers[0] = in;
04143       start = NULL;
04144 
04145       for (retry = 0; retry < 2; retry++) {
04146          numlines = 0;
04147          for (o = outgoing; o; o = o->q_next) { /* Keep track of important channels */
04148             if (o->stillgoing) { /* Keep track of important channels */
04149                stillgoing = 1;
04150                if (o->chan) {
04151                   if (pos < AST_MAX_WATCHERS) {
04152                      watchers[pos++] = o->chan;
04153                   }
04154                   if (!start) {
04155                      start = o;
04156                   } else {
04157                      prev->call_next = o;
04158                   }
04159                   prev = o;
04160                }
04161             }
04162             numlines++;
04163          }
04164          if (pos > 1 /* found */ || !stillgoing /* nobody listening */ ||
04165             (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) /* ring would not be delivered */) {
04166             break;
04167          }
04168          /* On "ringall" strategy we only move to the next penalty level
04169             when *all* ringing phones are done in the current penalty level */
04170          ring_one(qe, outgoing, &numbusies);
04171          /* and retry... */
04172       }
04173       if (pos == 1 /* not found */) {
04174          if (numlines == (numbusies + numnochan)) {
04175             ast_debug(1, "Everyone is busy at this time\n");
04176          } else {
04177             ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
04178          }
04179          *to = 0;
04180          return NULL;
04181       }
04182 
04183       /* Poll for events from both the incoming channel as well as any outgoing channels */
04184       winner = ast_waitfor_n(watchers, pos, to);
04185 
04186       /* Service all of the outgoing channels */
04187       for (o = start; o; o = o->call_next) {
04188          /* We go with a fixed buffer here instead of using ast_strdupa. Using
04189           * ast_strdupa in a loop like this one can cause a stack overflow
04190           */
04191          char ochan_name[AST_CHANNEL_NAME];
04192 
04193          if (o->chan) {
04194             ast_channel_lock(o->chan);
04195             ast_copy_string(ochan_name, ast_channel_name(o->chan), sizeof(ochan_name));
04196             ast_channel_unlock(o->chan);
04197          }
04198          if (o->stillgoing && (o->chan) &&  (ast_channel_state(o->chan) == AST_STATE_UP)) {
04199             if (!peer) {
04200                ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
04201                if (!o->block_connected_update) {
04202                   if (o->pending_connected_update) {
04203                      if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
04204                         ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
04205                         ast_channel_update_connected_line(in, &o->connected, NULL);
04206                      }
04207                   } else if (!o->dial_callerid_absent) {
04208                      ast_channel_lock(o->chan);
04209                      ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(o->chan));
04210                      ast_channel_unlock(o->chan);
04211                      connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
04212                      if (ast_channel_connected_line_sub(o->chan, in, &connected_caller, 0) &&
04213                         ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
04214                         ast_channel_update_connected_line(in, &connected_caller, NULL);
04215                      }
04216                      ast_party_connected_line_free(&connected_caller);
04217                   }
04218                }
04219                if (o->aoc_s_rate_list) {
04220                   size_t encoded_size;
04221                   struct ast_aoc_encoded *encoded;
04222                   if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
04223                      ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
04224                      ast_aoc_destroy_encoded(encoded);
04225                   }
04226                }
04227                peer = o;
04228             }
04229          } else if (o->chan && (o->chan == winner)) {
04230 
04231             ast_copy_string(on, o->member->interface, sizeof(on));
04232             ast_copy_string(membername, o->member->membername, sizeof(membername));
04233 
04234             /* Before processing channel, go ahead and check for forwarding */
04235             if (!ast_strlen_zero(ast_channel_call_forward(o->chan)) && !forwardsallowed) {
04236                ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, ast_channel_call_forward(o->chan));
04237                numnochan++;
04238                do_hang(o);
04239                winner = NULL;
04240                continue;
04241             } else if (!ast_strlen_zero(ast_channel_call_forward(o->chan))) {
04242                struct ast_channel *original = o->chan;
04243                char tmpchan[256];
04244                char *stuff;
04245                char *tech;
04246 
04247                ast_copy_string(tmpchan, ast_channel_call_forward(o->chan), sizeof(tmpchan));
04248                if ((stuff = strchr(tmpchan, '/'))) {
04249                   *stuff++ = '\0';
04250                   tech = tmpchan;
04251                } else {
04252                   snprintf(tmpchan, sizeof(tmpchan), "%s@%s", ast_channel_call_forward(o->chan), ast_channel_context(o->chan));
04253                   stuff = tmpchan;
04254                   tech = "Local";
04255                }
04256                if (!strcasecmp(tech, "Local")) {
04257                   /*
04258                    * Drop the connected line update block for local channels since
04259                    * this is going to run dialplan and the user can change his
04260                    * mind about what connected line information he wants to send.
04261                    */
04262                   o->block_connected_update = 0;
04263                }
04264 
04265                ast_cel_report_event(in, AST_CEL_FORWARD, NULL, ast_channel_call_forward(o->chan), NULL);
04266 
04267                ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
04268                /* Setup parameters */
04269                o->chan = ast_request(tech, ast_channel_nativeformats(in), in, stuff, &status);
04270                if (!o->chan) {
04271                   ast_log(LOG_NOTICE,
04272                      "Forwarding failed to create channel to dial '%s/%s'\n",
04273                      tech, stuff);
04274                   o->stillgoing = 0;
04275                   numnochan++;
04276                } else {
04277                   ast_channel_lock_both(o->chan, original);
04278                   ast_party_redirecting_copy(ast_channel_redirecting(o->chan),
04279                      ast_channel_redirecting(original));
04280                   ast_channel_unlock(o->chan);
04281                   ast_channel_unlock(original);
04282 
04283                   ast_channel_lock_both(o->chan, in);
04284                   ast_channel_inherit_variables(in, o->chan);
04285                   ast_channel_datastore_inherit(in, o->chan);
04286 
04287                   if (o->pending_connected_update) {
04288                      /*
04289                       * Re-seed the callattempt's connected line information with
04290                       * previously acquired connected line info from the queued
04291                       * channel.  The previously acquired connected line info could
04292                       * have been set through the CONNECTED_LINE dialplan function.
04293                       */
04294                      o->pending_connected_update = 0;
04295                      ast_party_connected_line_copy(&o->connected, ast_channel_connected(in));
04296                   }
04297 
04298                   ast_channel_accountcode_set(o->chan, ast_channel_accountcode(in));
04299 
04300                   if (!ast_channel_redirecting(o->chan)->from.number.valid
04301                      || ast_strlen_zero(ast_channel_redirecting(o->chan)->from.number.str)) {
04302                      /*
04303                       * The call was not previously redirected so it is
04304                       * now redirected from this number.
04305                       */
04306                      ast_party_number_free(&ast_channel_redirecting(o->chan)->from.number);
04307                      ast_party_number_init(&ast_channel_redirecting(o->chan)->from.number);
04308                      ast_channel_redirecting(o->chan)->from.number.valid = 1;
04309                      ast_channel_redirecting(o->chan)->from.number.str =
04310                         ast_strdup(S_OR(ast_channel_macroexten(in), ast_channel_exten(in)));
04311                   }
04312 
04313                   ast_channel_dialed(o->chan)->transit_network_select = ast_channel_dialed(in)->transit_network_select;
04314 
04315                   o->dial_callerid_absent = !ast_channel_caller(o->chan)->id.number.valid
04316                      || ast_strlen_zero(ast_channel_caller(o->chan)->id.number.str);
04317                   ast_connected_line_copy_from_caller(ast_channel_connected(o->chan),
04318                      ast_channel_caller(in));
04319 
04320                   ast_channel_unlock(in);
04321                   if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL
04322                      && !o->block_connected_update) {
04323                      struct ast_party_redirecting redirecting;
04324 
04325                      /*
04326                       * Redirecting updates to the caller make sense only on single
04327                       * call at a time strategies.
04328                       *
04329                       * We must unlock o->chan before calling
04330                       * ast_channel_redirecting_macro, because we put o->chan into
04331                       * autoservice there.  That is pretty much a guaranteed
04332                       * deadlock.  This is why the handling of o->chan's lock may
04333                       * seem a bit unusual here.
04334                       */
04335                      ast_party_redirecting_init(&redirecting);
04336                      ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(o->chan));
04337                      ast_channel_unlock(o->chan);
04338                      if (ast_channel_redirecting_sub(o->chan, in, &redirecting, 0) &&
04339                         ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0)) {
04340                         ast_channel_update_redirecting(in, &redirecting, NULL);
04341                      }
04342                      ast_party_redirecting_free(&redirecting);
04343                   } else {
04344                      ast_channel_unlock(o->chan);
04345                   }
04346 
04347                   if (ast_call(o->chan, stuff, 0)) {
04348                      ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
04349                         tech, stuff);
04350                      do_hang(o);
04351                      numnochan++;
04352                   }
04353                }
04354                /* Hangup the original channel now, in case we needed it */
04355                ast_hangup(winner);
04356                continue;
04357             }
04358             f = ast_read(winner);
04359             if (f) {
04360                if (f->frametype == AST_FRAME_CONTROL) {
04361                   switch (f->subclass.integer) {
04362                   case AST_CONTROL_ANSWER:
04363                      /* This is our guy if someone answered. */
04364                      if (!peer) {
04365                         ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
04366                         if (!o->block_connected_update) {
04367                            if (o->pending_connected_update) {
04368                               if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
04369                                  ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
04370                                  ast_channel_update_connected_line(in, &o->connected, NULL);
04371                               }
04372                            } else if (!o->dial_callerid_absent) {
04373                               ast_channel_lock(o->chan);
04374                               ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(o->chan));
04375                               ast_channel_unlock(o->chan);
04376                               connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
04377                               if (ast_channel_connected_line_sub(o->chan, in, &connected_caller, 0) &&
04378                                  ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
04379                                  ast_channel_update_connected_line(in, &connected_caller, NULL);
04380                               }
04381                               ast_party_connected_line_free(&connected_caller);
04382                            }
04383                         }
04384                         if (o->aoc_s_rate_list) {
04385                            size_t encoded_size;
04386                            struct ast_aoc_encoded *encoded;
04387                            if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
04388                               ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
04389                               ast_aoc_destroy_encoded(encoded);
04390                            }
04391                         }
04392                         peer = o;
04393                      }
04394                      break;
04395                   case AST_CONTROL_BUSY:
04396                      ast_verb(3, "%s is busy\n", ochan_name);
04397                      if (ast_channel_cdr(in)) {
04398                         ast_cdr_busy(ast_channel_cdr(in));
04399                      }
04400                      do_hang(o);
04401                      endtime = (long) time(NULL);
04402                      endtime -= starttime;
04403                      rna(endtime * 1000, qe, on, membername, qe->parent->autopausebusy);
04404                      if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
04405                         if (qe->parent->timeoutrestart) {
04406                            start_time_tv = ast_tvnow();
04407                         }
04408                         /* Have enough time for a queue member to answer? */
04409                         if (ast_remaining_ms(start_time_tv, orig) > 500) {
04410                            ring_one(qe, outgoing, &numbusies);
04411                            starttime = (long) time(NULL);
04412                         }
04413                      }
04414                      numbusies++;
04415                      break;
04416                   case AST_CONTROL_CONGESTION:
04417                      ast_verb(3, "%s is circuit-busy\n", ochan_name);
04418                      if (ast_channel_cdr(in)) {
04419                         ast_cdr_busy(ast_channel_cdr(in));
04420                      }
04421                      endtime = (long) time(NULL);
04422                      endtime -= starttime;
04423                      rna(endtime * 1000, qe, on, membername, qe->parent->autopauseunavail);
04424                      do_hang(o);
04425                      if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
04426                         if (qe->parent->timeoutrestart) {
04427                            start_time_tv = ast_tvnow();
04428                         }
04429                         if (ast_remaining_ms(start_time_tv, orig) > 500) {
04430                            ring_one(qe, outgoing, &numbusies);
04431                            starttime = (long) time(NULL);
04432                         }
04433                      }
04434                      numbusies++;
04435                      break;
04436                   case AST_CONTROL_RINGING:
04437                      ast_verb(3, "%s is ringing\n", ochan_name);
04438 
04439                      /* Start ring indication when the channel is ringing, if specified */
04440                      if (qe->ring_when_ringing) {
04441                         ast_moh_stop(qe->chan);
04442                         ast_indicate(qe->chan, AST_CONTROL_RINGING);
04443                      }
04444                      break;
04445                   case AST_CONTROL_OFFHOOK:
04446                      /* Ignore going off hook */
04447                      break;
04448                   case AST_CONTROL_CONNECTED_LINE:
04449                      if (o->block_connected_update) {
04450                         ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
04451                         break;
04452                      }
04453                      if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
04454                         struct ast_party_connected_line connected;
04455 
04456                         ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
04457                         ast_party_connected_line_set_init(&connected, &o->connected);
04458                         ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
04459                         ast_party_connected_line_set(&o->connected, &connected, NULL);
04460                         ast_party_connected_line_free(&connected);
04461                         o->pending_connected_update = 1;
04462                         break;
04463                      }
04464 
04465                      /*
04466                       * Prevent using the CallerID from the outgoing channel since we
04467                       * got a connected line update from it.
04468                       */
04469                      o->dial_callerid_absent = 1;
04470 
04471                      if (ast_channel_connected_line_sub(o->chan, in, f, 1) &&
04472                         ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
04473                         ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
04474                      }
04475                      break;
04476                   case AST_CONTROL_AOC:
04477                      {
04478                         struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
04479                         if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) {
04480                            ast_aoc_destroy_decoded(o->aoc_s_rate_list);
04481                            o->aoc_s_rate_list = decoded;
04482                         } else {
04483                            ast_aoc_destroy_decoded(decoded);
04484                         }
04485                      }
04486                      break;
04487                   case AST_CONTROL_REDIRECTING:
04488                      if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
04489                         /*
04490                          * Redirecting updates to the caller make sense only on single
04491                          * call at a time strategies.
04492                          */
04493                         break;
04494                      }
04495                      if (o->block_connected_update) {
04496                         ast_verb(3, "Redirecting update to %s prevented\n",
04497                            inchan_name);
04498                         break;
04499                      }
04500                      ast_verb(3, "%s redirecting info has changed, passing it to %s\n",
04501                         ochan_name, inchan_name);
04502                      if (ast_channel_redirecting_sub(o->chan, in, f, 1) &&
04503                         ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {
04504                         ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
04505                      }
04506                      break;
04507                   case AST_CONTROL_PVT_CAUSE_CODE:
04508                      ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);
04509                      break;
04510                   default:
04511                      ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
04512                      break;
04513                   }
04514                }
04515                ast_frfree(f);
04516             } else { /* ast_read() returned NULL */
04517                endtime = (long) time(NULL) - starttime;
04518                rna(endtime * 1000, qe, on, membername, 1);
04519                do_hang(o);
04520                if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
04521                   if (qe->parent->timeoutrestart) {
04522                      start_time_tv = ast_tvnow();
04523                   }
04524                   if (ast_remaining_ms(start_time_tv, orig) > 500) {
04525                      ring_one(qe, outgoing, &numbusies);
04526                      starttime = (long) time(NULL);
04527                   }
04528                }
04529             }
04530          }
04531       }
04532 
04533       /* If we received an event from the caller, deal with it. */
04534       if (winner == in) {
04535          f = ast_read(in);
04536          if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
04537             /* Got hung up */
04538             *to = -1;
04539             if (f) {
04540                if (f->data.uint32) {
04541                   ast_channel_hangupcause_set(in, f->data.uint32);
04542                }
04543                ast_frfree(f);
04544             }
04545             return NULL;
04546          }
04547 
04548          if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
04549             ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
04550             *to = 0;
04551             ast_frfree(f);
04552             return NULL;
04553          }
04554          if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
04555             ast_verb(3, "User pressed digit: %c\n", f->subclass.integer);
04556             *to = 0;
04557             *digit = f->subclass.integer;
04558             ast_frfree(f);
04559             return NULL;
04560          }
04561 
04562          /* Send the frame from the in channel to all outgoing channels. */
04563          for (o = start; o; o = o->call_next) {
04564             if (!o->stillgoing || !o->chan) {
04565                /* This outgoing channel has died so don't send the frame to it. */
04566                continue;
04567             }
04568             switch (f->frametype) {
04569             case AST_FRAME_CONTROL:
04570                switch (f->subclass.integer) {
04571                case AST_CONTROL_CONNECTED_LINE:
04572                   if (ast_channel_connected_line_sub(in, o->chan, f, 1) &&
04573                      ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) {
04574                      ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
04575                   }
04576                   break;
04577                case AST_CONTROL_REDIRECTING:
04578                   if (ast_channel_redirecting_sub(in, o->chan, f, 1) &&
04579                      ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) {
04580                      ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
04581                   }
04582                   break;
04583                default:
04584                   /* We are not going to do anything with this frame. */
04585                   goto skip_frame;
04586                }
04587                break;
04588             default:
04589                /* We are not going to do anything with this frame. */
04590                goto skip_frame;
04591             }
04592          }
04593 skip_frame:;
04594 
04595          ast_frfree(f);
04596       }
04597    }
04598 
04599    /* Make a position announcement, if enabled */
04600    if (qe->parent->announcefrequency && qe->parent->announce_to_first_user) {
04601       say_position(qe, ringing);
04602    }
04603 
04604    /* Make a periodic announcement, if enabled */
04605    if (qe->parent->periodicannouncefrequency && qe->parent->announce_to_first_user) {
04606       say_periodic_announcement(qe, ringing);
04607    }
04608 
04609    if (!*to) {
04610       for (o = start; o; o = o->call_next) {
04611          rna(orig, qe, o->interface, o->member->membername, 1);
04612       }
04613    }
04614 
04615 #ifdef HAVE_EPOLL
04616    for (epollo = outgoing; epollo; epollo = epollo->q_next) {
04617       if (epollo->chan) {
04618          ast_poll_channel_del(in, epollo->chan);
04619       }
04620    }
04621 #endif
04622 
04623    return peer;
04624 }
04625 
04626 /*!
04627  * \brief Check if we should start attempting to call queue members.
04628  *
04629  * A simple process, really. Count the number of members who are available
04630  * to take our call and then see if we are in a position in the queue at
04631  * which a member could accept our call.
04632  *
04633  * \param[in] qe The caller who wants to know if it is his turn
04634  * \retval 0 It is not our turn
04635  * \retval 1 It is our turn
04636  */
04637 static int is_our_turn(struct queue_ent *qe)
04638 {
04639    struct queue_ent *ch;
04640    int res;
04641    int avl;
04642    int idx = 0;
04643    /* This needs a lock. How many members are available to be served? */
04644    ao2_lock(qe->parent);
04645 
04646    avl = num_available_members(qe->parent);
04647 
04648    ch = qe->parent->head;
04649 
04650    ast_debug(1, "There %s %d available %s.\n", avl != 1 ? "are" : "is", avl, avl != 1 ? "members" : "member");
04651 
04652    while ((idx < avl) && (ch) && (ch != qe)) {
04653       if (!ch->pending) {
04654          idx++;
04655       }
04656       ch = ch->next;
04657    }
04658 
04659    ao2_unlock(qe->parent);
04660    /* If the queue entry is within avl [the number of available members] calls from the top ...
04661     * Autofill and position check added to support autofill=no (as only calls
04662     * from the front of the queue are valid when autofill is disabled)
04663     */
04664    if (ch && idx < avl && (qe->parent->autofill || qe->pos == 1)) {
04665       ast_debug(1, "It's our turn (%s).\n", ast_channel_name(qe->chan));
04666       res = 1;
04667    } else {
04668       ast_debug(1, "It's not our turn (%s).\n", ast_channel_name(qe->chan));
04669       res = 0;
04670    }
04671 
04672    return res;
04673 }
04674 
04675 /*!
04676  * \brief update rules for queues
04677  *
04678  * Calculate min/max penalties making sure if relative they stay within bounds.
04679  * Update queues penalty and set dialplan vars, goto next list entry.
04680 */
04681 static void update_qe_rule(struct queue_ent *qe)
04682 {
04683    int max_penalty = INT_MAX;
04684 
04685    if (qe->max_penalty != INT_MAX) {
04686       char max_penalty_str[20];
04687 
04688       if (qe->pr->max_relative) {
04689          max_penalty = qe->max_penalty + qe->pr->max_value;
04690       } else {
04691          max_penalty = qe->pr->max_value;
04692       }
04693 
04694       /* a relative change to the penalty could put it below 0 */
04695       if (max_penalty < 0) {
04696          max_penalty = 0;
04697       }
04698 
04699       snprintf(max_penalty_str, sizeof(max_penalty_str), "%d", max_penalty);
04700       pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
04701       qe->max_penalty = max_penalty;
04702       ast_debug(3, "Setting max penalty to %d for caller %s since %d seconds have elapsed\n",
04703          qe->max_penalty, ast_channel_name(qe->chan), qe->pr->time);
04704    }
04705 
04706    if (qe->min_penalty != INT_MAX) {
04707       char min_penalty_str[20];
04708       int min_penalty;
04709 
04710       if (qe->pr->min_relative) {
04711          min_penalty = qe->min_penalty + qe->pr->min_value;
04712       } else {
04713          min_penalty = qe->pr->min_value;
04714       }
04715 
04716       /* a relative change to the penalty could put it below 0 */
04717       if (min_penalty < 0) {
04718          min_penalty = 0;
04719       }
04720 
04721       if (max_penalty != INT_MAX && min_penalty > max_penalty) {
04722          min_penalty = max_penalty;
04723       }
04724 
04725       snprintf(min_penalty_str, sizeof(min_penalty_str), "%d", min_penalty);
04726       pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
04727       qe->min_penalty = min_penalty;
04728       ast_debug(3, "Setting min penalty to %d for caller %s since %d seconds have elapsed\n",
04729          qe->min_penalty, ast_channel_name(qe->chan), qe->pr->time);
04730    }
04731 
04732    qe->pr = AST_LIST_NEXT(qe->pr, list);
04733 }
04734 
04735 /*! \brief The waiting areas for callers who are not actively calling members
04736  *
04737  * This function is one large loop. This function will return if a caller
04738  * either exits the queue or it becomes that caller's turn to attempt calling
04739  * queue members. Inside the loop, we service the caller with periodic announcements,
04740  * holdtime announcements, etc. as configured in queues.conf
04741  *
04742  * \retval  0 if the caller's turn has arrived
04743  * \retval -1 if the caller should exit the queue.
04744  */
04745 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
04746 {
04747    int res = 0;
04748 
04749    /* This is the holding pen for callers 2 through maxlen */
04750    for (;;) {
04751 
04752       if (is_our_turn(qe)) {
04753          break;
04754       }
04755 
04756       /* If we have timed out, break out */
04757       if (qe->expire && (time(NULL) >= qe->expire)) {
04758          *reason = QUEUE_TIMEOUT;
04759          break;
04760       }
04761 
04762       if (qe->parent->leavewhenempty) {
04763          int status = 0;
04764 
04765          if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->parent->leavewhenempty))) {
04766             *reason = QUEUE_LEAVEEMPTY;
04767             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);
04768             leave_queue(qe);
04769             break;
04770          }
04771       }
04772 
04773       /* Make a position announcement, if enabled */
04774       if (qe->parent->announcefrequency &&
04775          (res = say_position(qe,ringing))) {
04776          break;
04777       }
04778 
04779       /* If we have timed out, break out */
04780       if (qe->expire && (time(NULL) >= qe->expire)) {
04781          *reason = QUEUE_TIMEOUT;
04782          break;
04783       }
04784 
04785       /* Make a periodic announcement, if enabled */
04786       if (qe->parent->periodicannouncefrequency &&
04787          (res = say_periodic_announcement(qe,ringing)))
04788          break;
04789 
04790       /* see if we need to move to the next penalty level for this queue */
04791       while (qe->pr && ((time(NULL) - qe->start) >= qe->pr->time)) {
04792          update_qe_rule(qe);
04793       }
04794 
04795       /* If we have timed out, break out */
04796       if (qe->expire && (time(NULL) >= qe->expire)) {
04797          *reason = QUEUE_TIMEOUT;
04798          break;
04799       }
04800 
04801       /* Wait a second before checking again */
04802       if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
04803          if (res > 0 && !valid_exit(qe, res)) {
04804             res = 0;
04805          } else {
04806             break;
04807          }
04808       }
04809 
04810       /* If we have timed out, break out */
04811       if (qe->expire && (time(NULL) >= qe->expire)) {
04812          *reason = QUEUE_TIMEOUT;
04813          break;
04814       }
04815    }
04816 
04817    return res;
04818 }
04819 
04820 /*!
04821  * \brief update the queue status
04822  * \retval Always 0
04823 */
04824 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, int newtalktime)
04825 {
04826    int oldtalktime;
04827 
04828    struct member *mem;
04829    struct call_queue *qtmp;
04830    struct ao2_iterator queue_iter;
04831 
04832    if (shared_lastcall) {
04833       queue_iter = ao2_iterator_init(queues, 0);
04834       while ((qtmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
04835          ao2_lock(qtmp);
04836          if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
04837             time(&mem->lastcall);
04838             mem->calls++;
04839             mem->lastqueue = q;
04840             ao2_ref(mem, -1);
04841          }
04842          ao2_unlock(qtmp);
04843          queue_t_unref(qtmp, "Done with iterator");
04844       }
04845       ao2_iterator_destroy(&queue_iter);
04846    } else {
04847       ao2_lock(q);
04848       time(&member->lastcall);
04849       member->calls++;
04850       member->lastqueue = q;
04851       ao2_unlock(q);
04852    }
04853    ao2_lock(q);
04854    q->callscompleted++;
04855    if (callcompletedinsl) {
04856       q->callscompletedinsl++;
04857    }
04858    /* Calculate talktime using the same exponential average as holdtime code*/
04859    oldtalktime = q->talktime;
04860    q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
04861    ao2_unlock(q);
04862    return 0;
04863 }
04864 
04865 /*! \brief Calculate the metric of each member in the outgoing callattempts
04866  *
04867  * A numeric metric is given to each member depending on the ring strategy used
04868  * by the queue. Members with lower metrics will be called before members with
04869  * higher metrics
04870  * \retval -1 if penalties are exceeded
04871  * \retval 0 otherwise
04872  */
04873 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
04874 {
04875    /* disregarding penalty on too few members? */
04876    int membercount = ao2_container_count(q->members);
04877    unsigned char usepenalty = (membercount <= q->penaltymemberslimit) ? 0 : 1;
04878 
04879    if (usepenalty) {
04880       if ((qe->max_penalty != INT_MAX && mem->penalty > qe->max_penalty) ||
04881          (qe->min_penalty != INT_MAX && mem->penalty < qe->min_penalty)) {
04882          return -1;
04883       }
04884    } else {
04885       ast_debug(1, "Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
04886            membercount, q->penaltymemberslimit);
04887    }
04888 
04889    switch (q->strategy) {
04890    case QUEUE_STRATEGY_RINGALL:
04891       /* Everyone equal, except for penalty */
04892       tmp->metric = mem->penalty * 1000000 * usepenalty;
04893       break;
04894    case QUEUE_STRATEGY_LINEAR:
04895       if (pos < qe->linpos) {
04896          tmp->metric = 1000 + pos;
04897       } else {
04898          if (pos > qe->linpos) {
04899             /* Indicate there is another priority */
04900             qe->linwrapped = 1;
04901          }
04902          tmp->metric = pos;
04903       }
04904       tmp->metric += mem->penalty * 1000000 * usepenalty;
04905       break;
04906    case QUEUE_STRATEGY_RRORDERED:
04907    case QUEUE_STRATEGY_RRMEMORY:
04908       pos = mem->queuepos;
04909       if (pos < q->rrpos) {
04910          tmp->metric = 1000 + pos;
04911       } else {
04912          if (pos > q->rrpos) {
04913             /* Indicate there is another priority */
04914             q->wrapped = 1;
04915          }
04916          tmp->metric = pos;
04917       }
04918       tmp->metric += mem->penalty * 1000000 * usepenalty;
04919       break;
04920    case QUEUE_STRATEGY_RANDOM:
04921       tmp->metric = ast_random() % 1000;
04922       tmp->metric += mem->penalty * 1000000 * usepenalty;
04923       break;
04924    case QUEUE_STRATEGY_WRANDOM:
04925       tmp->metric = ast_random() % ((1 + mem->penalty) * 1000);
04926       break;
04927    case QUEUE_STRATEGY_FEWESTCALLS:
04928       tmp->metric = mem->calls;
04929       tmp->metric += mem->penalty * 1000000 * usepenalty;
04930       break;
04931    case QUEUE_STRATEGY_LEASTRECENT:
04932       if (!mem->lastcall) {
04933          tmp->metric = 0;
04934       } else {
04935          tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
04936       }
04937       tmp->metric += mem->penalty * 1000000 * usepenalty;
04938       break;
04939    default:
04940       ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
04941       break;
04942    }
04943    return 0;
04944 }
04945 
04946 enum agent_complete_reason {
04947    CALLER,
04948    AGENT,
04949    TRANSFER
04950 };
04951 
04952 /*! \brief Send out AMI message with member call completion status information */
04953 static void send_agent_complete(const struct queue_ent *qe, const char *queuename,
04954    const struct ast_channel *peer, const struct member *member, time_t callstart,
04955    char *vars, size_t vars_len, enum agent_complete_reason rsn)
04956 {
04957    const char *reason = NULL; /* silence dumb compilers */
04958 
04959    if (!qe->parent->eventwhencalled) {
04960       return;
04961    }
04962 
04963    switch (rsn) {
04964    case CALLER:
04965       reason = "caller";
04966       break;
04967    case AGENT:
04968       reason = "agent";
04969       break;
04970    case TRANSFER:
04971       reason = "transfer";
04972       break;
04973    }
04974 
04975    /*** DOCUMENTATION
04976    <managerEventInstance>
04977       <synopsis>Raised when an agent has finished servicing a member in the queue.</synopsis>
04978       <syntax>
04979          <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
04980          <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='Member'])" />
04981          <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
04982          <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
04983          <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentCalled']/managerEventInstance/syntax/parameter[@name='Variable'])" />
04984          <parameter name="TalkTime">
04985             <para>The time the agent talked with the member in the queue, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
04986          </parameter>
04987          <parameter name="Reason">
04988             <enumlist>
04989                <enum name="caller"/>
04990                <enum name="agent"/>
04991                <enum name="transfer"/>
04992             </enumlist>
04993          </parameter>
04994       </syntax>
04995       <see-also>
04996          <ref type="managerEvent">AgentCalled</ref>
04997          <ref type="managerEvent">AgentConnect</ref>
04998       </see-also>
04999    </managerEventInstance>
05000    ***/
05001    manager_event(EVENT_FLAG_AGENT, "AgentComplete",
05002       "Queue: %s\r\n"
05003       "Uniqueid: %s\r\n"
05004       "Channel: %s\r\n"
05005       "Member: %s\r\n"
05006       "MemberName: %s\r\n"
05007       "HoldTime: %ld\r\n"
05008       "TalkTime: %ld\r\n"
05009       "Reason: %s\r\n"
05010       "%s",
05011       queuename, ast_channel_uniqueid(qe->chan), ast_channel_name(peer), member->interface, member->membername,
05012       (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
05013       qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
05014 }
05015 
05016 struct queue_transfer_ds {
05017    struct queue_ent *qe;
05018    struct member *member;
05019    time_t starttime;
05020    int callcompletedinsl;
05021 };
05022 
05023 static void queue_transfer_destroy(void *data)
05024 {
05025    struct queue_transfer_ds *qtds = data;
05026    ast_free(qtds);
05027 }
05028 
05029 /*! \brief a datastore used to help correctly log attended transfers of queue callers
05030  */
05031 static const struct ast_datastore_info queue_transfer_info = {
05032    .type = "queue_transfer",
05033    .chan_fixup = queue_transfer_fixup,
05034    .destroy = queue_transfer_destroy,
05035 };
05036 
05037 /*! \brief Log an attended transfer when a queue caller channel is masqueraded
05038  *
05039  * When a caller is masqueraded, we want to log a transfer. Fixup time is the closest we can come to when
05040  * the actual transfer occurs. This happens during the masquerade after datastores are moved from old_chan
05041  * to new_chan. This is why new_chan is referenced for exten, context, and datastore information.
05042  *
05043  * At the end of this, we want to remove the datastore so that this fixup function is not called on any
05044  * future masquerades of the caller during the current call.
05045  */
05046 static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
05047 {
05048    struct queue_transfer_ds *qtds = data;
05049    struct queue_ent *qe = qtds->qe;
05050    struct member *member = qtds->member;
05051    time_t callstart = qtds->starttime;
05052    int callcompletedinsl = qtds->callcompletedinsl;
05053    struct ast_datastore *datastore;
05054 
05055    ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), member->membername, "TRANSFER", "%s|%s|%ld|%ld|%d",
05056             ast_channel_exten(new_chan), ast_channel_context(new_chan), (long) (callstart - qe->start),
05057             (long) (time(NULL) - callstart), qe->opos);
05058 
05059    update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart));
05060 
05061    /* No need to lock the channels because they are already locked in ast_do_masquerade */
05062    if ((datastore = ast_channel_datastore_find(old_chan, &queue_transfer_info, NULL))) {
05063       ast_channel_datastore_remove(old_chan, datastore);
05064    } else {
05065       ast_log(LOG_WARNING, "Can't find the queue_transfer datastore.\n");
05066    }
05067 }
05068 
05069 /*! \brief mechanism to tell if a queue caller was atxferred by a queue member.
05070  *
05071  * When a caller is atxferred, then the queue_transfer_info datastore
05072  * is removed from the channel. If it's still there after the bridge is
05073  * broken, then the caller was not atxferred.
05074  *
05075  * \note Only call this with chan locked
05076  */
05077 static int attended_transfer_occurred(struct ast_channel *chan)
05078 {
05079    return ast_channel_datastore_find(chan, &queue_transfer_info, NULL) ? 0 : 1;
05080 }
05081 
05082 /*! \brief create a datastore for storing relevant info to log attended transfers in the queue_log
05083  */
05084 static struct ast_datastore *setup_transfer_datastore(struct queue_ent *qe, struct member *member, time_t starttime, int callcompletedinsl)
05085 {
05086    struct ast_datastore *ds;
05087    struct queue_transfer_ds *qtds = ast_calloc(1, sizeof(*qtds));
05088 
05089    if (!qtds) {
05090       ast_log(LOG_WARNING, "Memory allocation error!\n");
05091       return NULL;
05092    }
05093 
05094    ast_channel_lock(qe->chan);
05095    if (!(ds = ast_datastore_alloc(&queue_transfer_info, NULL))) {
05096       ast_channel_unlock(qe->chan);
05097       ast_free(qtds);
05098       ast_log(LOG_WARNING, "Unable to create transfer datastore. queue_log will not show attended transfer\n");
05099       return NULL;
05100    }
05101 
05102    qtds->qe = qe;
05103    /* This member is refcounted in try_calling, so no need to add it here, too */
05104    qtds->member = member;
05105    qtds->starttime = starttime;
05106    qtds->callcompletedinsl = callcompletedinsl;
05107    ds->data = qtds;
05108    ast_channel_datastore_add(qe->chan, ds);
05109    ast_channel_unlock(qe->chan);
05110    return ds;
05111 }
05112 
05113 struct queue_end_bridge {
05114    struct call_queue *q;
05115    struct ast_channel *chan;
05116 };
05117 
05118 static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
05119 {
05120    struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
05121    ao2_ref(qeb, +1);
05122    qeb->chan = originator;
05123 }
05124 
05125 static void end_bridge_callback(void *data)
05126 {
05127    struct queue_end_bridge *qeb = data;
05128    struct call_queue *q = qeb->q;
05129    struct ast_channel *chan = qeb->chan;
05130 
05131    if (ao2_ref(qeb, -1) == 1) {
05132       set_queue_variables(q, chan);
05133       /* This unrefs the reference we made in try_calling when we allocated qeb */
05134       queue_t_unref(q, "Expire bridge_config reference");
05135    }
05136 }
05137 
05138 /*!
05139  * \internal
05140  * \brief A large function which calls members, updates statistics, and bridges the caller and a member
05141  *
05142  * Here is the process of this function
05143  * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
05144  * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member. During this
05145  *    iteration, we also check the dialed_interfaces datastore to see if we have already attempted calling this
05146  *    member. If we have, we do not create a callattempt. This is in place to prevent call forwarding loops. Also
05147  *    during each iteration, we call calc_metric to determine which members should be rung when.
05148  * 3. Call ring_one to place a call to the appropriate member(s)
05149  * 4. Call wait_for_answer to wait for an answer. If no one answers, return.
05150  * 5. Take care of any holdtime announcements, member delays, or other options which occur after a call has been answered.
05151  * 6. Start the monitor or mixmonitor if the option is set
05152  * 7. Remove the caller from the queue to allow other callers to advance
05153  * 8. Bridge the call.
05154  * 9. Do any post processing after the call has disconnected.
05155  *
05156  * \param[in] qe the queue_ent structure which corresponds to the caller attempting to reach members
05157  * \param[in] opts the options passed as the third parameter to the Queue() application
05158  * \param[in] opt_args the options passed as the third parameter to the Queue() application
05159  * \param[in] announceoverride filename to play to user when waiting
05160  * \param[in] url the url passed as the fourth parameter to the Queue() application
05161  * \param[in,out] tries the number of times we have tried calling queue members
05162  * \param[out] noption set if the call to Queue() has the 'n' option set.
05163  * \param[in] agi the agi passed as the fifth parameter to the Queue() application
05164  * \param[in] macro the macro passed as the sixth parameter to the Queue() application
05165  * \param[in] gosub the gosub passed as the seventh parameter to the Queue() application
05166  * \param[in] ringing 1 if the 'r' option is set, otherwise 0
05167  */
05168 static int try_calling(struct queue_ent *qe, const 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)
05169 {
05170    struct member *cur;
05171    struct callattempt *outgoing = NULL; /* the list of calls we are building */
05172    int to, orig;
05173    char oldexten[AST_MAX_EXTENSION]="";
05174    char oldcontext[AST_MAX_CONTEXT]="";
05175    char queuename[256]="";
05176    char interfacevar[256]="";
05177    struct ast_channel *peer;
05178    struct ast_channel *which;
05179    struct callattempt *lpeer;
05180    struct member *member;
05181    struct ast_app *application;
05182    int res = 0, bridge = 0;
05183    int numbusies = 0;
05184    int x=0;
05185    char *announce = NULL;
05186    char digit = 0;
05187    time_t callstart;
05188    time_t now = time(NULL);
05189    struct ast_bridge_config bridge_config;
05190    char nondataquality = 1;
05191    char *agiexec = NULL;
05192    char *macroexec = NULL;
05193    char *gosubexec = NULL;
05194    const char *monitorfilename;
05195    const char *monitor_exec;
05196    const char *monitor_options;
05197    char tmpid[256], tmpid2[256];
05198    char meid[1024], meid2[1024];
05199    char mixmonargs[1512];
05200    struct ast_app *mixmonapp = NULL;
05201    char *p;
05202    char vars[2048];
05203    int forwardsallowed = 1;
05204    int block_connected_line = 0;
05205    int callcompletedinsl;
05206    struct ao2_iterator memi;
05207    struct ast_datastore *datastore, *transfer_ds;
05208    struct queue_end_bridge *queue_end_bridge = NULL;
05209 
05210    ast_channel_lock(qe->chan);
05211    datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
05212    ast_channel_unlock(qe->chan);
05213 
05214    memset(&bridge_config, 0, sizeof(bridge_config));
05215    tmpid[0] = 0;
05216    meid[0] = 0;
05217    time(&now);
05218 
05219    /* If we've already exceeded our timeout, then just stop
05220     * This should be extremely rare. queue_exec will take care
05221     * of removing the caller and reporting the timeout as the reason.
05222     */
05223    if (qe->expire && now >= qe->expire) {
05224       res = 0;
05225       goto out;
05226    }
05227 
05228    if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER)) {
05229       ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
05230    }
05231    if (ast_test_flag(&opts, OPT_CALLER_TRANSFER)) {
05232       ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
05233    }
05234    if (ast_test_flag(&opts, OPT_CALLEE_AUTOMON)) {
05235       ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
05236    }
05237    if (ast_test_flag(&opts, OPT_CALLER_AUTOMON)) {
05238       ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
05239    }
05240    if (ast_test_flag(&opts, OPT_GO_ON)) {
05241       ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_NO_H_EXTEN);
05242    }
05243    if (ast_test_flag(&opts, OPT_DATA_QUALITY)) {
05244       nondataquality = 0;
05245    }
05246    if (ast_test_flag(&opts, OPT_CALLEE_HANGUP)) {
05247       ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
05248    }
05249    if (ast_test_flag(&opts, OPT_CALLER_HANGUP)) {
05250       ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
05251    }
05252    if (ast_test_flag(&opts, OPT_CALLEE_PARK)) {
05253       ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
05254    }
05255    if (ast_test_flag(&opts, OPT_CALLER_PARK)) {
05256       ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
05257    }
05258    if (ast_test_flag(&opts, OPT_NO_RETRY)) {
05259       if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR
05260          || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
05261          (*tries)++;
05262       } else {
05263          *tries = ao2_container_count(qe->parent->members);
05264       }
05265       *noption = 1;
05266    }
05267    if (ast_test_flag(&opts, OPT_IGNORE_CALL_FW)) {
05268       forwardsallowed = 0;
05269    }
05270    if (ast_test_flag(&opts, OPT_IGNORE_CONNECTEDLINE)) {
05271       block_connected_line = 1;
05272    }
05273    if (ast_test_flag(&opts, OPT_CALLEE_AUTOMIXMON)) {
05274       ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
05275    }
05276    if (ast_test_flag(&opts, OPT_CALLER_AUTOMIXMON)) {
05277       ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
05278    }
05279    if (ast_test_flag(&opts, OPT_MARK_AS_ANSWERED)) {
05280       qe->cancel_answered_elsewhere = 1;
05281    }
05282 
05283    /* if the calling channel has AST_CAUSE_ANSWERED_ELSEWHERE set, make sure this is inherited.
05284       (this is mainly to support chan_local)
05285    */
05286    if (ast_channel_hangupcause(qe->chan) == AST_CAUSE_ANSWERED_ELSEWHERE) {
05287       qe->cancel_answered_elsewhere = 1;
05288    }
05289 
05290    ao2_lock(qe->parent);
05291    ast_debug(1, "%s is trying to call a queue member.\n",
05292                      ast_channel_name(qe->chan));
05293    ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
05294    if (!ast_strlen_zero(qe->announce)) {
05295       announce = qe->announce;
05296    }
05297    if (!ast_strlen_zero(announceoverride)) {
05298       announce = announceoverride;
05299    }
05300 
05301    memi = ao2_iterator_init(qe->parent->members, 0);
05302    while ((cur = ao2_iterator_next(&memi))) {
05303       struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
05304       struct ast_dialed_interface *di;
05305       AST_LIST_HEAD(,ast_dialed_interface) *dialed_interfaces;
05306       if (!tmp) {
05307          ao2_ref(cur, -1);
05308          ao2_iterator_destroy(&memi);
05309          ao2_unlock(qe->parent);
05310          goto out;
05311       }
05312       if (!datastore) {
05313          if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {
05314             callattempt_free(tmp);
05315             ao2_ref(cur, -1);
05316             ao2_iterator_destroy(&memi);
05317             ao2_unlock(qe->parent);
05318             goto out;
05319          }
05320          datastore->inheritance = DATASTORE_INHERIT_FOREVER;
05321          if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
05322             callattempt_free(tmp);
05323             ao2_ref(cur, -1);
05324             ao2_iterator_destroy(&memi);
05325             ao2_unlock(qe->parent);
05326             goto out;
05327          }
05328          datastore->data = dialed_interfaces;
05329          AST_LIST_HEAD_INIT(dialed_interfaces);
05330 
05331          ast_channel_lock(qe->chan);
05332          ast_channel_datastore_add(qe->chan, datastore);
05333          ast_channel_unlock(qe->chan);
05334       } else
05335          dialed_interfaces = datastore->data;
05336 
05337       AST_LIST_LOCK(dialed_interfaces);
05338       AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
05339          if (!strcasecmp(cur->interface, di->interface)) {
05340             ast_debug(1, "Skipping dialing interface '%s' since it has already been dialed\n",
05341                di->interface);
05342             break;
05343          }
05344       }
05345       AST_LIST_UNLOCK(dialed_interfaces);
05346 
05347       if (di) {
05348          callattempt_free(tmp);
05349          ao2_ref(cur, -1);
05350          continue;
05351       }
05352 
05353       /* It is always ok to dial a Local interface.  We only keep track of
05354        * which "real" interfaces have been dialed.  The Local channel will
05355        * inherit this list so that if it ends up dialing a real interface,
05356        * it won't call one that has already been called. */
05357       if (strncasecmp(cur->interface, "Local/", 6)) {
05358          if (!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {
05359             callattempt_free(tmp);
05360             ao2_ref(cur, -1);
05361             ao2_iterator_destroy(&memi);
05362             ao2_unlock(qe->parent);
05363             goto out;
05364          }
05365          strcpy(di->interface, cur->interface);
05366 
05367          AST_LIST_LOCK(dialed_interfaces);
05368          AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
05369          AST_LIST_UNLOCK(dialed_interfaces);
05370       }
05371 
05372       /*
05373        * Seed the callattempt's connected line information with previously
05374        * acquired connected line info from the queued channel.  The
05375        * previously acquired connected line info could have been set
05376        * through the CONNECTED_LINE dialplan function.
05377        */
05378       ast_channel_lock(qe->chan);
05379       ast_party_connected_line_copy(&tmp->connected, ast_channel_connected(qe->chan));
05380       ast_channel_unlock(qe->chan);
05381 
05382       tmp->block_connected_update = block_connected_line;
05383       tmp->stillgoing = 1;
05384       tmp->member = cur;/* Place the reference for cur into callattempt. */
05385       tmp->lastcall = cur->lastcall;
05386       tmp->lastqueue = cur->lastqueue;
05387       ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
05388       /* Special case: If we ring everyone, go ahead and ring them, otherwise
05389          just calculate their metric for the appropriate strategy */
05390       if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
05391          /* Put them in the list of outgoing thingies...  We're ready now.
05392             XXX If we're forcibly removed, these outgoing calls won't get
05393             hung up XXX */
05394          tmp->q_next = outgoing;
05395          outgoing = tmp;
05396          /* If this line is up, don't try anybody else */
05397          if (outgoing->chan && (ast_channel_state(outgoing->chan) == AST_STATE_UP))
05398             break;
05399       } else {
05400          callattempt_free(tmp);
05401       }
05402    }
05403    ao2_iterator_destroy(&memi);
05404 
05405    if (qe->parent->timeoutpriority == TIMEOUT_PRIORITY_APP) {
05406       /* Application arguments have higher timeout priority (behaviour for <=1.6) */
05407       if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout)) {
05408          to = (qe->expire - now) * 1000;
05409       } else {
05410          to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
05411       }
05412    } else {
05413       /* Config timeout is higher priority thatn application timeout */
05414       if (qe->expire && qe->expire<=now) {
05415          to = 0;
05416       } else if (qe->parent->timeout) {
05417          to = qe->parent->timeout * 1000;
05418       } else {
05419          to = -1;
05420       }
05421    }
05422    orig = to;
05423    ++qe->pending;
05424    ao2_unlock(qe->parent);
05425    ring_one(qe, outgoing, &numbusies);
05426    lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies,
05427       ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT),
05428       forwardsallowed, ringing);
05429    /* The ast_channel_datastore_remove() function could fail here if the
05430     * datastore was moved to another channel during a masquerade. If this is
05431     * the case, don't free the datastore here because later, when the channel
05432     * to which the datastore was moved hangs up, it will attempt to free this
05433     * datastore again, causing a crash
05434     */
05435    ast_channel_lock(qe->chan);
05436    if (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) {
05437       ast_datastore_free(datastore);
05438    }
05439    ast_channel_unlock(qe->chan);
05440    ao2_lock(qe->parent);
05441    if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
05442       store_next_rr(qe, outgoing);
05443 
05444    }
05445    if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
05446       store_next_lin(qe, outgoing);
05447    }
05448    ao2_unlock(qe->parent);
05449    peer = lpeer ? lpeer->chan : NULL;
05450    if (!peer) {
05451       qe->pending = 0;
05452       if (to) {
05453          /* Must gotten hung up */
05454          res = -1;
05455       } else {
05456          /* User exited by pressing a digit */
05457          res = digit;
05458       }
05459       if (res == -1) {
05460          ast_debug(1, "%s: Nobody answered.\n", ast_channel_name(qe->chan));
05461       }
05462       if (ast_cdr_isset_unanswered()) {
05463          /* channel contains the name of one of the outgoing channels
05464             in its CDR; zero out this CDR to avoid a dual-posting */
05465          struct callattempt *o;
05466          for (o = outgoing; o; o = o->q_next) {
05467             if (!o->chan) {
05468                continue;
05469             }
05470             if (strcmp(ast_channel_cdr(o->chan)->dstchannel, ast_channel_cdr(qe->chan)->dstchannel) == 0) {
05471                ast_set_flag(ast_channel_cdr(o->chan), AST_CDR_FLAG_POST_DISABLED);
05472                break;
05473             }
05474          }
05475       }
05476    } else { /* peer is valid */
05477       /* These variables are used with the F option without arguments (callee jumps to next priority after queue) */
05478       char *caller_context;
05479       char *caller_extension;
05480       int caller_priority;
05481 
05482       /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
05483          we will always return with -1 so that it is hung up properly after the
05484          conversation.  */
05485       if (!strcmp(ast_channel_tech(qe->chan)->type, "DAHDI")) {
05486          ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
05487       }
05488       if (!strcmp(ast_channel_tech(peer)->type, "DAHDI")) {
05489          ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
05490       }
05491       /* Update parameters for the queue */
05492       time(&now);
05493       recalc_holdtime(qe, (now - qe->start));
05494       ao2_lock(qe->parent);
05495       callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
05496       ao2_unlock(qe->parent);
05497       member = lpeer->member;
05498       /* Increment the refcount for this member, since we're going to be using it for awhile in here. */
05499       ao2_ref(member, 1);
05500       hangupcalls(outgoing, peer, qe->cancel_answered_elsewhere);
05501       outgoing = NULL;
05502       if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
05503          int res2;
05504 
05505          res2 = ast_autoservice_start(qe->chan);
05506          if (!res2) {
05507             if (qe->parent->memberdelay) {
05508                ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
05509                res2 = ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
05510             }
05511             if (!res2 && announce) {
05512                if (play_file(peer, announce) < 0) {
05513                   ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", announce, ast_channel_name(peer));
05514                }
05515             }
05516             if (!res2 && qe->parent->reportholdtime) {
05517                if (!play_file(peer, qe->parent->sound_reporthold)) {
05518                   int holdtime, holdtimesecs;
05519 
05520                   time(&now);
05521                   holdtime = abs((now - qe->start) / 60);
05522                   holdtimesecs = abs((now - qe->start) % 60);
05523                   if (holdtime > 0) {
05524                      ast_say_number(peer, holdtime, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
05525                      if (play_file(peer, qe->parent->sound_minutes) < 0) {
05526                         ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_minutes, ast_channel_name(peer));
05527                      }
05528                   }
05529                   if (holdtimesecs > 1) {
05530                      ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
05531                      if (play_file(peer, qe->parent->sound_seconds) < 0) {
05532                         ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_seconds, ast_channel_name(peer));
05533                      }
05534                   }
05535                }
05536             }
05537             ast_autoservice_stop(qe->chan);
05538          }
05539          if (ast_check_hangup(peer)) {
05540             /* Agent must have hung up */
05541             ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", ast_channel_name(peer));
05542             ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "AGENTDUMP", "%s", "");
05543             if (qe->parent->eventwhencalled)
05544                /*** DOCUMENTATION
05545                <managerEventInstance>
05546                   <synopsis>Raised when an agent hangs up on a member in the queue.</synopsis>
05547                   <syntax>
05548                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
05549                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='Member'])" />
05550                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
05551                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentCalled']/managerEventInstance/syntax/parameter[@name='Variable'])" />
05552                   </syntax>
05553                   <see-also>
05554                      <ref type="managerEvent">AgentCalled</ref>
05555                      <ref type="managerEvent">AgentConnect</ref>
05556                   </see-also>
05557                </managerEventInstance>
05558                ***/
05559                manager_event(EVENT_FLAG_AGENT, "AgentDump",
05560                      "Queue: %s\r\n"
05561                      "Uniqueid: %s\r\n"
05562                      "Channel: %s\r\n"
05563                      "Member: %s\r\n"
05564                      "MemberName: %s\r\n"
05565                      "%s",
05566                      queuename, ast_channel_uniqueid(qe->chan), ast_channel_name(peer), member->interface, member->membername,
05567                      qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
05568             ast_autoservice_chan_hangup_peer(qe->chan, peer);
05569             ao2_ref(member, -1);
05570             goto out;
05571          } else if (ast_check_hangup(qe->chan)) {
05572             /* Caller must have hung up just before being connected */
05573             ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", ast_channel_name(peer));
05574             ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
05575             record_abandoned(qe);
05576             ast_autoservice_chan_hangup_peer(qe->chan, peer);
05577             ao2_ref(member, -1);
05578             return -1;
05579          }
05580       }
05581       /* Stop music on hold */
05582       if (ringing) {
05583          ast_indicate(qe->chan,-1);
05584       } else {
05585          ast_moh_stop(qe->chan);
05586       }
05587       /* If appropriate, log that we have a destination channel */
05588       if (ast_channel_cdr(qe->chan)) {
05589          ast_cdr_setdestchan(ast_channel_cdr(qe->chan), ast_channel_name(peer));
05590       }
05591       /* Make sure channels are compatible */
05592       res = ast_channel_make_compatible(qe->chan, peer);
05593       if (res < 0) {
05594          ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "SYSCOMPAT", "%s", "");
05595          ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", ast_channel_name(qe->chan), ast_channel_name(peer));
05596          record_abandoned(qe);
05597          ast_cdr_failed(ast_channel_cdr(qe->chan));
05598          ast_autoservice_chan_hangup_peer(qe->chan, peer);
05599          ao2_ref(member, -1);
05600          return -1;
05601       }
05602 
05603       /* Play announcement to the caller telling it's his turn if defined */
05604       if (!ast_strlen_zero(qe->parent->sound_callerannounce)) {
05605          if (play_file(qe->chan, qe->parent->sound_callerannounce)) {
05606             ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", qe->parent->sound_callerannounce);
05607          }
05608       }
05609 
05610       ao2_lock(qe->parent);
05611       /* if setinterfacevar is defined, make member variables available to the channel */
05612       /* use  pbx_builtin_setvar to set a load of variables with one call */
05613       if (qe->parent->setinterfacevar) {
05614          snprintf(interfacevar, sizeof(interfacevar), "MEMBERINTERFACE=%s,MEMBERNAME=%s,MEMBERCALLS=%d,MEMBERLASTCALL=%ld,MEMBERPENALTY=%d,MEMBERDYNAMIC=%d,MEMBERREALTIME=%d",
05615             member->interface, member->membername, member->calls, (long)member->lastcall, member->penalty, member->dynamic, member->realtime);
05616          pbx_builtin_setvar_multiple(qe->chan, interfacevar);
05617          pbx_builtin_setvar_multiple(peer, interfacevar);
05618       }
05619 
05620       /* if setqueueentryvar is defined, make queue entry (i.e. the caller) variables available to the channel */
05621       /* use  pbx_builtin_setvar to set a load of variables with one call */
05622       if (qe->parent->setqueueentryvar) {
05623          snprintf(interfacevar, sizeof(interfacevar), "QEHOLDTIME=%ld,QEORIGINALPOS=%d",
05624             (long) time(NULL) - qe->start, qe->opos);
05625          pbx_builtin_setvar_multiple(qe->chan, interfacevar);
05626          pbx_builtin_setvar_multiple(peer, interfacevar);
05627       }
05628 
05629       ao2_unlock(qe->parent);
05630 
05631       /* try to set queue variables if configured to do so*/
05632       set_queue_variables(qe->parent, qe->chan);
05633       set_queue_variables(qe->parent, peer);
05634 
05635       ast_channel_lock(qe->chan);
05636       /* Copy next destination data for 'F' option (no args) */
05637       caller_context = ast_strdupa(ast_channel_context(qe->chan));
05638       caller_extension = ast_strdupa(ast_channel_exten(qe->chan));
05639       caller_priority = ast_channel_priority(qe->chan);
05640       if ((monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME"))) {
05641             monitorfilename = ast_strdupa(monitorfilename);
05642       }
05643       ast_channel_unlock(qe->chan);
05644 
05645       /* Begin Monitoring */
05646       if (qe->parent->monfmt && *qe->parent->monfmt) {
05647          if (!qe->parent->montype) {
05648             const char *monexec;
05649             ast_debug(1, "Starting Monitor as requested.\n");
05650             ast_channel_lock(qe->chan);
05651             if ((monexec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC")) || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS")) {
05652                which = qe->chan;
05653                monexec = monexec ? ast_strdupa(monexec) : NULL;
05654             } else {
05655                which = peer;
05656             }
05657             ast_channel_unlock(qe->chan);
05658             if (monitorfilename) {
05659                ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT);
05660             } else if (ast_channel_cdr(qe->chan)) {
05661                ast_monitor_start(which, qe->parent->monfmt, ast_channel_cdr(qe->chan)->uniqueid, 1, X_REC_IN | X_REC_OUT);
05662             } else {
05663                /* Last ditch effort -- no CDR, make up something */
05664                snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
05665                ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT);
05666             }
05667             if (!ast_strlen_zero(monexec)) {
05668                ast_monitor_setjoinfiles(which, 1);
05669             }
05670          } else {
05671             mixmonapp = pbx_findapp("MixMonitor");
05672 
05673             if (mixmonapp) {
05674                ast_debug(1, "Starting MixMonitor as requested.\n");
05675                if (!monitorfilename) {
05676                   if (ast_channel_cdr(qe->chan)) {
05677                      ast_copy_string(tmpid, ast_channel_cdr(qe->chan)->uniqueid, sizeof(tmpid));
05678                   } else {
05679                      snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
05680                   }
05681                } else {
05682                   const char *m = monitorfilename;
05683                   for (p = tmpid2; p < tmpid2 + sizeof(tmpid2) - 1; p++, m++) {
05684                      switch (*m) {
05685                      case '^':
05686                         if (*(m + 1) == '{')
05687                            *p = '$';
05688                         break;
05689                      case ',':
05690                         *p++ = '\\';
05691                         /* Fall through */
05692                      default:
05693                         *p = *m;
05694                      }
05695                      if (*m == '\0')
05696                         break;
05697                   }
05698                   if (p == tmpid2 + sizeof(tmpid2))
05699                      tmpid2[sizeof(tmpid2) - 1] = '\0';
05700 
05701                   pbx_substitute_variables_helper(qe->chan, tmpid2, tmpid, sizeof(tmpid) - 1);
05702                }
05703 
05704                ast_channel_lock(qe->chan);
05705                if ((monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC"))) {
05706                      monitor_exec = ast_strdupa(monitor_exec);
05707                }
05708                if ((monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS"))) {
05709                      monitor_options = ast_strdupa(monitor_options);
05710                } else {
05711                   monitor_options = "";
05712                }
05713                ast_channel_unlock(qe->chan);
05714 
05715                if (monitor_exec) {
05716                   const char *m = monitor_exec;
05717                   for (p = meid2; p < meid2 + sizeof(meid2) - 1; p++, m++) {
05718                      switch (*m) {
05719                      case '^':
05720                         if (*(m + 1) == '{')
05721                            *p = '$';
05722                         break;
05723                      case ',':
05724                         *p++ = '\\';
05725                         /* Fall through */
05726                      default:
05727                         *p = *m;
05728                      }
05729                      if (*m == '\0') {
05730                         break;
05731                      }
05732                   }
05733                   if (p == meid2 + sizeof(meid2)) {
05734                      meid2[sizeof(meid2) - 1] = '\0';
05735                   }
05736 
05737                   pbx_substitute_variables_helper(qe->chan, meid2, meid, sizeof(meid) - 1);
05738                }
05739 
05740                snprintf(tmpid2, sizeof(tmpid2), "%s.%s", tmpid, qe->parent->monfmt);
05741 
05742                if (!ast_strlen_zero(monitor_exec)) {
05743                   snprintf(mixmonargs, sizeof(mixmonargs), "%s,b%s,%s", tmpid2, monitor_options, monitor_exec);
05744                } else {
05745                   snprintf(mixmonargs, sizeof(mixmonargs), "%s,b%s", tmpid2, monitor_options);
05746                }
05747 
05748                ast_debug(1, "Arguments being passed to MixMonitor: %s\n", mixmonargs);
05749                /* We purposely lock the CDR so that pbx_exec does not update the application data */
05750                if (ast_channel_cdr(qe->chan)) {
05751                   ast_set_flag(ast_channel_cdr(qe->chan), AST_CDR_FLAG_LOCKED);
05752                }
05753                pbx_exec(qe->chan, mixmonapp, mixmonargs);
05754                if (ast_channel_cdr(qe->chan)) {
05755                   ast_clear_flag(ast_channel_cdr(qe->chan), AST_CDR_FLAG_LOCKED);
05756                }
05757             } else {
05758                ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");
05759             }
05760          }
05761       }
05762       /* Drop out of the queue at this point, to prepare for next caller */
05763       leave_queue(qe);
05764       if (!ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
05765          ast_debug(1, "app_queue: sendurl=%s.\n", url);
05766          ast_channel_sendurl(peer, url);
05767       }
05768 
05769       /* run a macro for this connection if defined. The macro simply returns, no action is taken on the result */
05770       /* use macro from dialplan if passed as a option, otherwise use the default queue macro */
05771       if (!ast_strlen_zero(macro)) {
05772          macroexec = ast_strdupa(macro);
05773       } else {
05774          if (qe->parent->membermacro) {
05775             macroexec = ast_strdupa(qe->parent->membermacro);
05776          }
05777       }
05778 
05779       if (!ast_strlen_zero(macroexec)) {
05780          ast_debug(1, "app_queue: macro=%s.\n", macroexec);
05781          ast_app_exec_macro(qe->chan, peer, macroexec);
05782       }
05783 
05784       /* run a gosub for this connection if defined. The gosub simply returns, no action is taken on the result */
05785       /* use gosub from dialplan if passed as a option, otherwise use the default queue gosub */
05786       if (!ast_strlen_zero(gosub)) {
05787          gosubexec = ast_strdupa(gosub);
05788       } else {
05789          if (qe->parent->membergosub) {
05790             gosubexec = ast_strdupa(qe->parent->membergosub);
05791          }
05792       }
05793 
05794       if (!ast_strlen_zero(gosubexec)) {
05795          char *gosub_args = NULL;
05796          char *gosub_argstart;
05797 
05798          ast_debug(1, "app_queue: gosub=%s.\n", gosubexec);
05799 
05800          gosub_argstart = strchr(gosubexec, ',');
05801          if (gosub_argstart) {
05802             const char *what_is_s = "s";
05803             *gosub_argstart = 0;
05804             if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL)) &&
05805                 ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL))) {
05806                what_is_s = "~~s~~";
05807             }
05808             if (ast_asprintf(&gosub_args, "%s,%s,1(%s)", gosubexec, what_is_s, gosub_argstart + 1) < 0) {
05809                gosub_args = NULL;
05810             }
05811             *gosub_argstart = ',';
05812          } else {
05813             const char *what_is_s = "s";
05814             if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL)) &&
05815                 ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL))) {
05816                what_is_s = "~~s~~";
05817             }
05818             if (ast_asprintf(&gosub_args, "%s,%s,1", gosubexec, what_is_s) < 0) {
05819                gosub_args = NULL;
05820             }
05821          }
05822          if (gosub_args) {
05823             ast_app_exec_sub(qe->chan, peer, gosub_args, 0);
05824             ast_free(gosub_args);
05825          } else {
05826             ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
05827          }
05828       }
05829 
05830       if (!ast_strlen_zero(agi)) {
05831          ast_debug(1, "app_queue: agi=%s.\n", agi);
05832          application = pbx_findapp("agi");
05833          if (application) {
05834             agiexec = ast_strdupa(agi);
05835             pbx_exec(qe->chan, application, agiexec);
05836          } else {
05837             ast_log(LOG_WARNING, "Asked to execute an AGI on this channel, but could not find application (agi)!\n");
05838          }
05839       }
05840       qe->handled++;
05841       ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "CONNECT", "%ld|%s|%ld", (long) time(NULL) - qe->start, ast_channel_uniqueid(peer),
05842                                        (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
05843 
05844       if (ast_channel_cdr(qe->chan)) {
05845          struct ast_cdr *cdr;
05846          struct ast_cdr *newcdr;
05847 
05848          /* Only work with the last CDR in the stack*/
05849          cdr = ast_channel_cdr(qe->chan);
05850          while (cdr->next) {
05851             cdr = cdr->next;
05852          }
05853 
05854          /* If this CDR is not related to us add new one*/
05855          if ((strcasecmp(cdr->uniqueid, ast_channel_uniqueid(qe->chan))) &&
05856              (strcasecmp(cdr->linkedid, ast_channel_uniqueid(qe->chan))) &&
05857              (newcdr = ast_cdr_dup(cdr))) {
05858             ast_channel_lock(qe->chan);
05859             ast_cdr_init(newcdr, qe->chan);
05860             ast_cdr_reset(newcdr, 0);
05861             cdr = ast_cdr_append(cdr, newcdr);
05862             cdr = cdr->next;
05863             ast_channel_unlock(qe->chan);
05864          }
05865 
05866          if (update_cdr) {
05867             ast_copy_string(cdr->dstchannel, member->membername, sizeof(cdr->dstchannel));
05868          }
05869       }
05870 
05871       if (qe->parent->eventwhencalled)
05872          /*** DOCUMENTATION
05873          <managerEventInstance>
05874             <synopsis>Raised when an agent answers and is bridged to a member in the queue.</synopsis>
05875             <syntax>
05876                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
05877                <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='Member'])" />
05878                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
05879                <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentRingNoAnswer']/managerEventInstance/syntax/parameter[@name='RingTime'])" />
05880                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueCallerAbandon']/managerEventInstance/syntax/parameter[@name='HoldTime'])" />
05881                <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentCalled']/managerEventInstance/syntax/parameter[@name='Variable'])" />
05882             </syntax>
05883             <see-also>
05884                <ref type="managerEvent">AgentCalled</ref>
05885                <ref type="managerEvent">AgentComplete</ref>
05886                <ref type="managerEvent">AgentDump</ref>
05887             </see-also>
05888          </managerEventInstance>
05889          ***/
05890          manager_event(EVENT_FLAG_AGENT, "AgentConnect",
05891                "Queue: %s\r\n"
05892                "Uniqueid: %s\r\n"
05893                "Channel: %s\r\n"
05894                "Member: %s\r\n"
05895                "MemberName: %s\r\n"
05896                "HoldTime: %ld\r\n"
05897                "BridgedChannel: %s\r\n"
05898                "RingTime: %ld\r\n"
05899                "%s",
05900                queuename, ast_channel_uniqueid(qe->chan), ast_channel_name(peer), member->interface, member->membername,
05901                (long) time(NULL) - qe->start, ast_channel_uniqueid(peer), (long)(orig - to > 0 ? (orig - to) / 1000 : 0),
05902                qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
05903       ast_copy_string(oldcontext, ast_channel_context(qe->chan), sizeof(oldcontext));
05904       ast_copy_string(oldexten, ast_channel_exten(qe->chan), sizeof(oldexten));
05905 
05906       if ((queue_end_bridge = ao2_alloc(sizeof(*queue_end_bridge), NULL))) {
05907          queue_end_bridge->q = qe->parent;
05908          queue_end_bridge->chan = qe->chan;
05909          bridge_config.end_bridge_callback = end_bridge_callback;
05910          bridge_config.end_bridge_callback_data = queue_end_bridge;
05911          bridge_config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
05912          /* Since queue_end_bridge can survive beyond the life of this call to Queue, we need
05913           * to make sure to increase the refcount of this queue so it cannot be freed until we
05914           * are done with it. We remove this reference in end_bridge_callback.
05915           */
05916          queue_t_ref(qe->parent, "For bridge_config reference");
05917       }
05918 
05919       time(&callstart);
05920       transfer_ds = setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
05921       bridge = ast_bridge_call(qe->chan, peer, &bridge_config);
05922 
05923       /* If the queue member did an attended transfer, then the TRANSFER already was logged in the queue_log
05924        * when the masquerade occurred. These other "ending" queue_log messages are unnecessary, except for
05925        * the AgentComplete manager event
05926        */
05927       ast_channel_lock(qe->chan);
05928       if (!attended_transfer_occurred(qe->chan)) {
05929          struct ast_datastore *tds;
05930 
05931          /* detect a blind transfer */
05932          if (!(ast_channel_softhangup_internal_flag(qe->chan) | ast_channel_softhangup_internal_flag(peer)) && (strcasecmp(oldcontext, ast_channel_context(qe->chan)) || strcasecmp(oldexten, ast_channel_exten(qe->chan)))) {
05933             ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "TRANSFER", "%s|%s|%ld|%ld|%d",
05934                ast_channel_exten(qe->chan), ast_channel_context(qe->chan), (long) (callstart - qe->start),
05935                (long) (time(NULL) - callstart), qe->opos);
05936             send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), TRANSFER);
05937          } else if (ast_check_hangup(qe->chan) && !ast_check_hangup(peer)) {
05938             ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "COMPLETECALLER", "%ld|%ld|%d",
05939                (long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
05940             send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), CALLER);
05941          } else {
05942             ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "COMPLETEAGENT", "%ld|%ld|%d",
05943                (long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
05944             send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), AGENT);
05945          }
05946          if ((tds = ast_channel_datastore_find(qe->chan, &queue_transfer_info, NULL))) {
05947             ast_channel_datastore_remove(qe->chan, tds);
05948          }
05949          ast_channel_unlock(qe->chan);
05950          update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart));
05951       } else {
05952          ast_channel_unlock(qe->chan);
05953 
05954          /* We already logged the TRANSFER on the queue_log, but we still need to send the AgentComplete event */
05955          send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), TRANSFER);
05956       }
05957 
05958       if (transfer_ds) {
05959          ast_datastore_free(transfer_ds);
05960       }
05961 
05962       if (!ast_check_hangup(peer) && ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
05963          int goto_res;
05964 
05965          if (!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
05966             ast_replace_subargument_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
05967             goto_res = ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
05968          } else { /* F() */
05969             goto_res = ast_goto_if_exists(peer, caller_context, caller_extension,
05970                caller_priority + 1);
05971          }
05972          if (goto_res || ast_pbx_start(peer)) {
05973             ast_autoservice_chan_hangup_peer(qe->chan, peer);
05974          }
05975       } else {
05976          ast_autoservice_chan_hangup_peer(qe->chan, peer);
05977       }
05978 
05979       res = bridge ? bridge : 1;
05980       ao2_ref(member, -1);
05981    }
05982 out:
05983    hangupcalls(outgoing, NULL, qe->cancel_answered_elsewhere);
05984 
05985    return res;
05986 }
05987 
05988 static int wait_a_bit(struct queue_ent *qe)
05989 {
05990    /* Don't need to hold the lock while we setup the outgoing calls */
05991    int retrywait = qe->parent->retry * 1000;
05992 
05993    int res = ast_waitfordigit(qe->chan, retrywait);
05994    if (res > 0 && !valid_exit(qe, res)) {
05995       res = 0;
05996    }
05997 
05998    return res;
05999 }
06000 
06001 static struct member *interface_exists(struct call_queue *q, const char *interface)
06002 {
06003    struct member *mem;
06004    struct ao2_iterator mem_iter;
06005 
06006    if (!q) {
06007       return NULL;
06008    }
06009    mem_iter = ao2_iterator_init(q->members, 0);
06010    while ((mem = ao2_iterator_next(&mem_iter))) {
06011       if (!strcasecmp(interface, mem->interface)) {
06012          ao2_iterator_destroy(&mem_iter);
06013          return mem;
06014       }
06015       ao2_ref(mem, -1);
06016    }
06017    ao2_iterator_destroy(&mem_iter);
06018 
06019    return NULL;
06020 }
06021 
06022 
06023 /*! \brief Dump all members in a specific queue to the database
06024  *
06025  * <pm_family>/<queuename> = <interface>;<penalty>;<paused>;<state_interface>[|...]
06026  */
06027 static void dump_queue_members(struct call_queue *pm_queue)
06028 {
06029    struct member *cur_member;
06030    struct ast_str *value;
06031    struct ao2_iterator mem_iter;
06032 
06033    if (!pm_queue) {
06034       return;
06035    }
06036 
06037    /* 4K is a reasonable default for most applications, but we grow to
06038     * accommodate more if necessary. */
06039    if (!(value = ast_str_create(4096))) {
06040       return;
06041    }
06042 
06043    mem_iter = ao2_iterator_init(pm_queue->members, 0);
06044    while ((cur_member = ao2_iterator_next(&mem_iter))) {
06045       if (!cur_member->dynamic) {
06046          ao2_ref(cur_member, -1);
06047          continue;
06048       }
06049 
06050       ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s",
06051          ast_str_strlen(value) ? "|" : "",
06052          cur_member->interface,
06053          cur_member->penalty,
06054          cur_member->paused,
06055          cur_member->membername,
06056          cur_member->state_interface);
06057 
06058       ao2_ref(cur_member, -1);
06059    }
06060    ao2_iterator_destroy(&mem_iter);
06061 
06062    if (ast_str_strlen(value) && !cur_member) {
06063       if (ast_db_put(pm_family, pm_queue->name, ast_str_buffer(value))) {
06064          ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
06065       }
06066    } else {
06067       /* Delete the entry if the queue is empty or there is an error */
06068       ast_db_del(pm_family, pm_queue->name);
06069    }
06070 
06071    ast_free(value);
06072 }
06073 
06074 /*! \brief Remove member from queue
06075  * \retval RES_NOT_DYNAMIC when they aren't a RT member
06076  * \retval RES_NOSUCHQUEUE queue does not exist
06077  * \retval RES_OKAY removed member from queue
06078  * \retval RES_EXISTS queue exists but no members
06079 */
06080 static int remove_from_queue(const char *queuename, const char *interface)
06081 {
06082    struct call_queue *q, tmpq = {
06083       .name = queuename,
06084    };
06085    struct member *mem, tmpmem;
06086    int res = RES_NOSUCHQUEUE;
06087 
06088    ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
06089    if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Temporary reference for interface removal"))) {
06090       ao2_lock(q);
06091       if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
06092          /* XXX future changes should beware of this assumption!! */
06093          /*Change Penalty on realtime users*/
06094          if (mem->realtime && !ast_strlen_zero(mem->rt_uniqueid) && negative_penalty_invalid) {
06095             update_realtime_member_field(mem, q->name, "penalty", "-1");
06096          } else if (!mem->dynamic) {
06097             ao2_ref(mem, -1);
06098             ao2_unlock(q);
06099             queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference");
06100             return RES_NOT_DYNAMIC;
06101          }
06102          /*** DOCUMENTATION
06103          <managerEventInstance>
06104             <synopsis>Raised when a member is removed from the queue.</synopsis>
06105             <syntax>
06106                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
06107                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Location'])" />
06108                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
06109             </syntax>
06110             <see-also>
06111                <ref type="managerEvent">QueueMemberAdded</ref>
06112                <ref type="application">RemoveQueueMember</ref>
06113             </see-also>
06114          </managerEventInstance>
06115          ***/
06116          manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
06117             "Queue: %s\r\n"
06118             "Location: %s\r\n"
06119             "MemberName: %s\r\n",
06120             q->name, mem->interface, mem->membername);
06121          member_remove_from_queue(q, mem);
06122          ao2_ref(mem, -1);
06123 
06124          if (queue_persistent_members) {
06125             dump_queue_members(q);
06126          }
06127 
06128          if (!num_available_members(q)) {
06129             ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
06130          }
06131 
06132          res = RES_OKAY;
06133       } else {
06134          res = RES_EXISTS;
06135       }
06136       ao2_unlock(q);
06137       queue_t_unref(q, "Expiring temporary reference");
06138    }
06139 
06140    return res;
06141 }
06142 
06143 /*! \brief Add member to queue
06144  * \retval RES_NOT_DYNAMIC when they aren't a RT member
06145  * \retval RES_NOSUCHQUEUE queue does not exist
06146  * \retval RES_OKAY added member from queue
06147  * \retval RES_EXISTS queue exists but no members
06148  * \retval RES_OUT_OF_MEMORY queue exists but not enough memory to create member
06149 */
06150 static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
06151 {
06152    struct call_queue *q;
06153    struct member *new_member, *old_member;
06154    int res = RES_NOSUCHQUEUE;
06155 
06156    /*! \note Ensure the appropriate realtime queue is loaded.  Note that this
06157     * short-circuits if the queue is already in memory. */
06158    if (!(q = find_load_queue_rt_friendly(queuename))) {
06159       return res;
06160    }
06161 
06162    ao2_lock(q);
06163    if ((old_member = interface_exists(q, interface)) == NULL) {
06164       if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface, q->ringinuse))) {
06165          new_member->ringinuse = q->ringinuse;
06166          new_member->dynamic = 1;
06167          member_add_to_queue(q, new_member);
06168          /*** DOCUMENTATION
06169          <managerEventInstance>
06170             <synopsis>Raised when a member is added to the queue.</synopsis>
06171             <syntax>
06172                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
06173                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Location'])" />
06174                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
06175                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='StateInterface'])" />
06176                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Membership'])" />
06177                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Penalty'])" />
06178                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='CallsTaken'])" />
06179                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='LastCall'])" />
06180                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Status'])" />
06181                <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Paused'])" />
06182             </syntax>
06183             <see-also>
06184                <ref type="managerEvent">QueueMemberRemoved</ref>
06185                <ref type="application">AddQueueMember</ref>
06186             </see-also>
06187          </managerEventInstance>
06188          ***/
06189          manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
06190             "Queue: %s\r\n"
06191             "Location: %s\r\n"
06192             "MemberName: %s\r\n"
06193             "StateInterface: %s\r\n"
06194             "Membership: %s\r\n"
06195             "Penalty: %d\r\n"
06196             "CallsTaken: %d\r\n"
06197             "LastCall: %d\r\n"
06198             "Status: %d\r\n"
06199             "Paused: %d\r\n",
06200             q->name, new_member->interface, new_member->membername, state_interface,
06201             "dynamic",
06202             new_member->penalty, new_member->calls, (int) new_member->lastcall,
06203             new_member->status, new_member->paused);
06204 
06205          if (is_member_available(q, new_member)) {
06206             ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
06207          }
06208 
06209          ao2_ref(new_member, -1);
06210          new_member = NULL;
06211 
06212          if (dump) {
06213             dump_queue_members(q);
06214          }
06215 
06216          res = RES_OKAY;
06217       } else {
06218          res = RES_OUTOFMEMORY;
06219       }
06220    } else {
06221       ao2_ref(old_member, -1);
06222       res = RES_EXISTS;
06223    }
06224    ao2_unlock(q);
06225    queue_t_unref(q, "Expiring temporary reference");
06226 
06227    return res;
06228 }
06229 
06230 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
06231 {
06232    int found = 0;
06233    struct call_queue *q;
06234    struct member *mem;
06235    struct ao2_iterator queue_iter;
06236    int failed;
06237 
06238    /* Special event for when all queues are paused - individual events still generated */
06239    /* XXX In all other cases, we use the membername, but since this affects all queues, we cannot */
06240    if (ast_strlen_zero(queuename))
06241       ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
06242 
06243    queue_iter = ao2_iterator_init(queues, 0);
06244    while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) {
06245       ao2_lock(q);
06246       if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
06247          if ((mem = interface_exists(q, interface))) {
06248             if (mem->paused == paused) {
06249                ast_debug(1, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
06250             }
06251 
06252             failed = 0;
06253             if (mem->realtime) {
06254                failed = update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0");
06255             }
06256 
06257             if (failed) {
06258                ast_log(LOG_WARNING, "Failed %spausing realtime queue member %s:%s\n", (paused ? "" : "un"), q->name, interface);
06259                ao2_ref(mem, -1);
06260                ao2_unlock(q);
06261                queue_t_unref(q, "Done with iterator");
06262                continue;
06263             }
06264             found++;
06265             mem->paused = paused;
06266 
06267             if (queue_persistent_members) {
06268                dump_queue_members(q);
06269             }
06270 
06271             if (is_member_available(q, mem)) {
06272                ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
06273             } else if (!num_available_members(q)) {
06274                ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Queue:%s_avail", q->name);
06275             }
06276 
06277             ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", S_OR(reason, ""));
06278 
06279             if (!ast_strlen_zero(reason)) {
06280                /*** DOCUMENTATION
06281                <managerEventInstance>
06282                   <synopsis>Raised when a member is paused/unpaused in the queue with a reason.</synopsis>
06283                   <syntax>
06284                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
06285                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Location'])" />
06286                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
06287                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Paused'])" />
06288                      <parameter name="Reason">
06289                         <para>The reason given for pausing or unpausing a queue member.</para>
06290                      </parameter>
06291                   </syntax>
06292                   <see-also>
06293                      <ref type="application">PauseQueueMember</ref>
06294                      <ref type="application">UnPauseQueueMember</ref>
06295                   </see-also>
06296                </managerEventInstance>
06297                ***/
06298                manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
06299                   "Queue: %s\r\n"
06300                   "Location: %s\r\n"
06301                   "MemberName: %s\r\n"
06302                   "Paused: %d\r\n"
06303                   "Reason: %s\r\n",
06304                      q->name, mem->interface, mem->membername, paused, reason);
06305             } else {
06306                /*** DOCUMENTATION
06307                <managerEventInstance>
06308                   <synopsis>Raised when a member is paused/unpaused in the queue without a reason.</synopsis>
06309                   <syntax>
06310                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
06311                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Location'])" />
06312                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='MemberName'])" />
06313                      <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Paused'])" />
06314                   </syntax>
06315                   <see-also>
06316                      <ref type="application">PauseQueueMember</ref>
06317                      <ref type="application">UnPauseQueueMember</ref>
06318                   </see-also>
06319                </managerEventInstance>
06320                ***/
06321                manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
06322                   "Queue: %s\r\n"
06323                   "Location: %s\r\n"
06324                   "MemberName: %s\r\n"
06325                   "Paused: %d\r\n",
06326                      q->name, mem->interface, mem->membername, paused);
06327             }
06328             ao2_ref(mem, -1);
06329          }
06330       }
06331 
06332       if (!ast_strlen_zero(queuename) && !strcasecmp(queuename, q->name)) {
06333          ao2_unlock(q);
06334          queue_t_unref(q, "Done with iterator");
06335          break;
06336       }
06337 
06338       ao2_unlock(q);
06339       queue_t_unref(q, "Done with iterator");
06340    }
06341    ao2_iterator_destroy(&queue_iter);
06342 
06343    return found ? RESULT_SUCCESS : RESULT_FAILURE;
06344 }
06345 
06346 /*!
06347  * \internal
06348  * \brief helper function for set_member_penalty - given a queue, sets all member penalties with the interface
06349  * \param[in] q queue which is having its member's penalty changed - must be unlocked prior to calling
06350  * \param[in] interface String of interface used to search for queue members being changed
06351  * \param[in] penalty Value penalty is being changed to for the member.
06352  * \retval 0 if the there is no member with interface belonging to q and no change is made
06353  * \retval 1 if the there is a member with interface belonging to q and changes are made
06354  */
06355 static int set_member_penalty_help_members(struct call_queue *q, const char *interface, int penalty)
06356 {
06357    struct member *mem;
06358    int foundinterface = 0;
06359    char rtpenalty[80];
06360 
06361    ao2_lock(q);
06362    if ((mem = interface_exists(q, interface))) {
06363       foundinterface++;
06364       if (!mem->realtime) {
06365          mem->penalty = penalty;
06366       } else {
06367          sprintf(rtpenalty, "%i", penalty);
06368          update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
06369       }
06370       ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
06371       /*** DOCUMENTATION
06372       <managerEventInstance>
06373          <synopsis>Raised when a member's penalty is changed.</synopsis>
06374          <syntax>
06375             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
06376             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Location'])" />
06377             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Penalty'])" />
06378          </syntax>
06379          <see-also>
06380             <ref type="function">QUEUE_MEMBER</ref>
06381          </see-also>
06382       </managerEventInstance>
06383       ***/
06384       manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
06385          "Queue: %s\r\n"
06386          "Location: %s\r\n"
06387          "Penalty: %d\r\n",
06388          q->name, mem->interface, penalty);
06389       ao2_ref(mem, -1);
06390    }
06391    ao2_unlock(q);
06392 
06393    return foundinterface;
06394 }
06395 
06396 static int set_member_ringinuse_help_members(struct call_queue *q, const char *interface, int ringinuse)
06397 {
06398    struct member *mem;
06399    int foundinterface = 0;
06400    char rtringinuse[80];
06401 
06402    ao2_lock(q);
06403    if ((mem = interface_exists(q, interface))) {
06404       foundinterface++;
06405       if (!mem->realtime) {
06406          mem->ringinuse = ringinuse;
06407       } else {
06408          sprintf(rtringinuse, "%i", ringinuse);
06409          update_realtime_member_field(mem, q->name, realtime_ringinuse_field, rtringinuse);
06410       }
06411       ast_queue_log(q->name, "NONE", interface, "RINGINUSE", "%d", ringinuse);
06412       /*** DOCUMENTATION
06413       <managerEventInstance>
06414          <synopsis>Raised when a member's ringinuse setting is changed.</synopsis>
06415          <syntax>
06416             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Queue'])" />
06417             <xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter[@name='Location'])" />
06418             <parameter name="Ringinuse">
06419                <enumlist>
06420                   <enum name="0"/>
06421                   <enum name="1"/>
06422                </enumlist>
06423             </parameter>
06424          </syntax>
06425          <see-also>
06426             <ref type="function">QUEUE_MEMBER</ref>
06427          </see-also>
06428       </managerEventInstance>
06429       ***/
06430       manager_event(EVENT_FLAG_AGENT, "QueueMemberRinginuse",
06431          "Queue: %s\r\n"
06432          "Location: %s\r\n"
06433          "Ringinuse: %d\r\n",
06434          q->name, mem->interface, ringinuse);
06435       ao2_ref(mem, -1);
06436    }
06437    ao2_unlock(q);
06438 
06439    return foundinterface;
06440 }
06441 
06442 static int set_member_value_help_members(struct call_queue *q, const char *interface, int property, int value)
06443 {
06444    switch(property) {
06445    case MEMBER_PENALTY:
06446       return set_member_penalty_help_members(q, interface, value);
06447 
06448    case MEMBER_RINGINUSE:
06449       return set_member_ringinuse_help_members(q, interface, value);
06450 
06451    default:
06452       ast_log(LOG_ERROR, "Attempted to set invalid property\n");
06453       return 0;
06454    }
06455 }
06456 
06457 /*!
06458  * \internal
06459  * \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues.
06460  * \param[in] queuename If specified, only act on a member if it belongs to this queue
06461  * \param[in] interface Interface of queue member(s) having priority set.
06462  * \param[in] property Which queue property is being set
06463  * \param[in] penalty Value penalty is being changed to for each member
06464  */
06465 static int set_member_value(const char *queuename, const char *interface, int property, int value)
06466 {
06467    int foundinterface = 0, foundqueue = 0;
06468    struct call_queue *q;
06469    struct ast_config *queue_config = NULL;
06470    struct ao2_iterator queue_iter;
06471 
06472    /* property dependent restrictions on values should be checked in this switch */
06473    switch (property) {
06474    case MEMBER_PENALTY:
06475       if (value < 0 && !negative_penalty_invalid) {
06476          ast_log(LOG_ERROR, "Invalid penalty (%d)\n", value);
06477          return RESULT_FAILURE;
06478       }
06479    }
06480 
06481    if (ast_strlen_zero(queuename)) { /* This means we need to iterate through all the queues. */
06482       if (ast_check_realtime("queues")) {
06483          char *name;
06484          queue_config = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
06485          if (queue_config) {
06486             for (name = ast_category_browse(queue_config, NULL);
06487                 !ast_strlen_zero(name);
06488                 name = ast_category_browse(queue_config, name)) {
06489                if ((q = find_load_queue_rt_friendly(name))) {
06490                   foundqueue++;
06491                   foundinterface += set_member_value_help_members(q, interface, property, value);
06492                }
06493             }
06494          }
06495       }
06496 
06497       /* After hitting realtime queues, go back and get the regular ones. */
06498       queue_iter = ao2_iterator_init(queues, 0);
06499       while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
06500          foundqueue++;
06501          foundinterface += set_member_value_help_members(q, interface, property, value);
06502       }
06503       ao2_iterator_destroy(&queue_iter);
06504    } else { /* We actually have a queuename, so we can just act on the single queue. */
06505       if ((q = find_load_queue_rt_friendly(queuename))) {
06506          foundqueue++;
06507          foundinterface += set_member_value_help_members(q, interface, property, value);
06508       }
06509    }
06510 
06511    if (foundinterface) {
06512       return RESULT_SUCCESS;
06513    } else if (!foundqueue) {
06514       ast_log (LOG_ERROR, "Invalid queuename\n");
06515    } else {
06516       ast_log (LOG_ERROR, "Invalid interface\n");
06517    }
06518 
06519    return RESULT_FAILURE;
06520 }
06521 
06522 /* \brief Gets members penalty.
06523  * \return Return the members penalty or RESULT_FAILURE on error.
06524 */
06525 static int get_member_penalty(char *queuename, char *interface)
06526 {
06527    int foundqueue = 0, penalty;
06528    struct call_queue *q, tmpq = {
06529       .name = queuename,
06530    };
06531    struct member *mem;
06532 
06533    if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Search for queue"))) {
06534       foundqueue = 1;
06535       ao2_lock(q);
06536       if ((mem = interface_exists(q, interface))) {
06537          penalty = mem->penalty;
06538          ao2_ref(mem, -1);
06539          ao2_unlock(q);
06540          queue_t_unref(q, "Search complete");
06541          return penalty;
06542       }
06543       ao2_unlock(q);
06544       queue_t_unref(q, "Search complete");
06545    }
06546 
06547    /* some useful debuging */
06548    if (foundqueue) {
06549       ast_log (LOG_ERROR, "Invalid queuename\n");
06550    } else {
06551       ast_log (LOG_ERROR, "Invalid interface\n");
06552    }
06553 
06554    return RESULT_FAILURE;
06555 }
06556 
06557 /*! \brief Reload dynamic queue members persisted into the astdb */
06558 static void reload_queue_members(void)
06559 {
06560    char *cur_ptr;
06561    const char *queue_name;
06562    char *member;
06563    char *interface;
06564    char *membername = NULL;
06565    char *state_interface;
06566    char *penalty_tok;
06567    int penalty = 0;
06568    char *paused_tok;
06569    int paused = 0;
06570    struct ast_db_entry *db_tree;
06571    struct ast_db_entry *entry;
06572    struct call_queue *cur_queue;
06573    char *queue_data;
06574 
06575    /* Each key in 'pm_family' is the name of a queue */
06576    db_tree = ast_db_gettree(pm_family, NULL);
06577    for (entry = db_tree; entry; entry = entry->next) {
06578 
06579       queue_name = entry->key + strlen(pm_family) + 2;
06580 
06581       {
06582          struct call_queue tmpq = {
06583             .name = queue_name,
06584          };
06585          cur_queue = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Reload queue members");
06586       }
06587 
06588       if (!cur_queue) {
06589          cur_queue = find_load_queue_rt_friendly(queue_name);
06590       }
06591 
06592       if (!cur_queue) {
06593          /* If the queue no longer exists, remove it from the
06594           * database */
06595          ast_log(LOG_WARNING, "Error loading persistent queue: '%s': it does not exist\n", queue_name);
06596          ast_db_del(pm_family, queue_name);
06597          continue;
06598       }
06599 
06600       if (ast_db_get_allocated(pm_family, queue_name, &queue_data)) {
06601          queue_t_unref(cur_queue, "Expire reload reference");
06602          continue;
06603       }
06604 
06605       cur_ptr = queue_data;
06606       while ((member = strsep(&cur_ptr, ",|"))) {
06607          if (ast_strlen_zero(member)) {
06608             continue;
06609          }
06610 
06611          interface = strsep(&member, ";");
06612          penalty_tok = strsep(&member, ";");
06613          paused_tok = strsep(&member, ";");
06614          membername = strsep(&member, ";");
06615          state_interface = strsep(&member, ";");
06616 
06617          if (!penalty_tok) {
06618             ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
06619             break;
06620          }
06621          penalty = strtol(penalty_tok, NULL, 10);
06622          if (errno == ERANGE) {
06623             ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok);
06624             break;
06625          }
06626 
06627          if (!paused_tok) {
06628             ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
06629             break;
06630          }
06631          paused = strtol(paused_tok, NULL, 10);
06632          if ((errno == ERANGE) || paused < 0 || paused > 1) {
06633             ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
06634             break;
06635          }
06636 
06637          ast_debug(1, "Reload Members: Queue: %s  Member: %s  Name: %s  Penalty: %d  Paused: %d\n", queue_name, interface, membername, penalty, paused);
06638 
06639          if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface) == RES_OUTOFMEMORY) {
06640             ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
06641             break;
06642          }
06643       }
06644       queue_t_unref(cur_queue, "Expire reload reference");
06645       ast_free(queue_data);
06646    }
06647 
06648    if (db_tree) {
06649       ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n");
06650       ast_db_freetree(db_tree);
06651    }
06652 }
06653 
06654 /*! \brief PauseQueueMember application */
06655 static int pqm_exec(struct ast_channel *chan, const char *data)
06656 {
06657    char *parse;
06658    AST_DECLARE_APP_ARGS(args,
06659       AST_APP_ARG(queuename);
06660       AST_APP_ARG(interface);
06661       AST_APP_ARG(options);
06662       AST_APP_ARG(reason);
06663    );
06664 
06665    if (ast_strlen_zero(data)) {
06666       ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename],interface[,options][,reason])\n");
06667       return -1;
06668    }
06669 
06670    parse = ast_strdupa(data);
06671 
06672    AST_STANDARD_APP_ARGS(args, parse);
06673 
06674    if (ast_strlen_zero(args.interface)) {
06675       ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
06676       return -1;
06677    }
06678 
06679    if (set_member_paused(args.queuename, args.interface, args.reason, 1)) {
06680       ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", args.interface);
06681       pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND");
06682       return 0;
06683    }
06684 
06685    pbx_builtin_setvar_helper(chan, "PQMSTATUS", "PAUSED");
06686 
06687    return 0;
06688 }
06689 
06690 /*! \brief UnPauseQueueMember application */
06691 static int upqm_exec(struct ast_channel *chan, const char *data)
06692 {
06693    char *parse;
06694    AST_DECLARE_APP_ARGS(args,
06695       AST_APP_ARG(queuename);
06696       AST_APP_ARG(interface);
06697       AST_APP_ARG(options);
06698       AST_APP_ARG(reason);
06699    );
06700 
06701    if (ast_strlen_zero(data)) {
06702       ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename],interface[,options[,reason]])\n");
06703       return -1;
06704    }
06705 
06706    parse = ast_strdupa(data);
06707 
06708    AST_STANDARD_APP_ARGS(args, parse);
06709 
06710    if (ast_strlen_zero(args.interface)) {
06711       ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
06712       return -1;
06713    }
06714 
06715    if (set_member_paused(args.queuename, args.interface, args.reason, 0)) {
06716       ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", args.interface);
06717       pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND");
06718       return 0;
06719    }
06720 
06721    pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "UNPAUSED");
06722 
06723    return 0;
06724 }
06725 
06726 /*! \brief RemoveQueueMember application */
06727 static int rqm_exec(struct ast_channel *chan, const char *data)
06728 {
06729    int res=-1;
06730    char *parse, *temppos = NULL;
06731    struct member *mem = NULL;
06732 
06733    AST_DECLARE_APP_ARGS(args,
06734       AST_APP_ARG(queuename);
06735       AST_APP_ARG(interface);
06736    );
06737 
06738 
06739    if (ast_strlen_zero(data)) {
06740       ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[,interface])\n");
06741       return -1;
06742    }
06743 
06744    parse = ast_strdupa(data);
06745 
06746    AST_STANDARD_APP_ARGS(args, parse);
06747 
06748    if (ast_strlen_zero(args.interface)) {
06749       args.interface = ast_strdupa(ast_channel_name(chan));
06750       temppos = strrchr(args.interface, '-');
06751       if (temppos) {
06752          *temppos = '\0';
06753       }
06754    }
06755 
06756    ast_debug(1, "queue: %s, member: %s\n", args.queuename, args.interface);
06757 
06758    if (log_membername_as_agent) {
06759       mem = find_member_by_queuename_and_interface(args.queuename, args.interface);
06760    }
06761 
06762    switch (remove_from_queue(args.queuename, args.interface)) {
06763    case RES_OKAY:
06764       if (!mem || ast_strlen_zero(mem->membername)) {
06765          ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "REMOVEMEMBER", "%s", "");
06766       } else {
06767          ast_queue_log(args.queuename, ast_channel_uniqueid(chan), mem->membername, "REMOVEMEMBER", "%s", "");
06768       }
06769       ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", args.interface, args.queuename);
06770       pbx_builtin_setvar_helper(chan, "RQMSTATUS", "REMOVED");
06771       res = 0;
06772       break;
06773    case RES_EXISTS:
06774       ast_debug(1, "Unable to remove interface '%s' from queue '%s': Not there\n", args.interface, args.queuename);
06775       pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTINQUEUE");
06776       res = 0;
06777       break;
06778    case RES_NOSUCHQUEUE:
06779       ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", args.queuename);
06780       pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOSUCHQUEUE");
06781       res = 0;
06782       break;
06783    case RES_NOT_DYNAMIC:
06784       ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': '%s' is not a dynamic member\n", args.queuename, args.interface);
06785       pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTDYNAMIC");
06786       res = 0;
06787       break;
06788    }
06789 
06790    if (mem) {
06791       ao2_ref(mem, -1);
06792    }
06793 
06794    return res;
06795 }
06796 
06797 /*! \brief AddQueueMember application */
06798 static int aqm_exec(struct ast_channel *chan, const char *data)
06799 {
06800    int res=-1;
06801    char *parse, *temppos = NULL;
06802    AST_DECLARE_APP_ARGS(args,
06803       AST_APP_ARG(queuename);
06804       AST_APP_ARG(interface);
06805       AST_APP_ARG(penalty);
06806       AST_APP_ARG(options);
06807       AST_APP_ARG(membername);
06808       AST_APP_ARG(state_interface);
06809    );
06810    int penalty = 0;
06811 
06812    if (ast_strlen_zero(data)) {
06813       ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface]]]]])\n");
06814       return -1;
06815    }
06816 
06817    parse = ast_strdupa(data);
06818 
06819    AST_STANDARD_APP_ARGS(args, parse);
06820 
06821    if (ast_strlen_zero(args.interface)) {
06822       args.interface = ast_strdupa(ast_channel_name(chan));
06823       temppos = strrchr(args.interface, '-');
06824       if (temppos) {
06825          *temppos = '\0';
06826       }
06827    }
06828 
06829    if (!ast_strlen_zero(args.penalty)) {
06830       if ((sscanf(args.penalty, "%30d", &penalty) != 1) || penalty < 0) {
06831          ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty);
06832          penalty = 0;
06833       }
06834    }
06835 
06836    switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface)) {
06837    case RES_OKAY:
06838       if (ast_strlen_zero(args.membername) || !log_membername_as_agent) {
06839          ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "ADDMEMBER", "%s", "");
06840       } else {
06841          ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.membername, "ADDMEMBER", "%s", "");
06842       }
06843       ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
06844       pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED");
06845       res = 0;
06846       break;
06847    case RES_EXISTS:
06848       ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename);
06849       pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY");
06850       res = 0;
06851       break;
06852    case RES_NOSUCHQUEUE:
06853       ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename);
06854       pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE");
06855       res = 0;
06856       break;
06857    case RES_OUTOFMEMORY:
06858       ast_log(LOG_ERROR, "Out of memory adding interface %s to queue %s\n", args.interface, args.queuename);
06859       break;
06860    }
06861 
06862    return res;
06863 }
06864 
06865 /*! \brief QueueLog application */
06866 static int ql_exec(struct ast_channel *chan, const char *data)
06867 {
06868    char *parse;
06869 
06870    AST_DECLARE_APP_ARGS(args,
06871       AST_APP_ARG(queuename);
06872       AST_APP_ARG(uniqueid);
06873       AST_APP_ARG(membername);
06874       AST_APP_ARG(event);
06875       AST_APP_ARG(params);
06876    );
06877 
06878    if (ast_strlen_zero(data)) {
06879       ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo]\n");
06880       return -1;
06881    }
06882 
06883    parse = ast_strdupa(data);
06884 
06885    AST_STANDARD_APP_ARGS(args, parse);
06886 
06887    if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.uniqueid)
06888        || ast_strlen_zero(args.membername) || ast_strlen_zero(args.event)) {
06889       ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo])\n");
06890       return -1;
06891    }
06892 
06893    ast_queue_log(args.queuename, args.uniqueid, args.membername, args.event,
06894       "%s", args.params ? args.params : "");
06895 
06896    return 0;
06897 }
06898 
06899 /*! \brief Copy rule from global list into specified queue */
06900 static void copy_rules(struct queue_ent *qe, const char *rulename)
06901 {
06902    struct penalty_rule *pr_iter;
06903    struct rule_list *rl_iter;
06904    const char *tmp = ast_strlen_zero(rulename) ? qe->parent->defaultrule : rulename;
06905    AST_LIST_LOCK(&rule_lists);
06906    AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
06907       if (!strcasecmp(rl_iter->name, tmp)) {
06908          break;
06909       }
06910    }
06911    if (rl_iter) {
06912       AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
06913          struct penalty_rule *new_pr = ast_calloc(1, sizeof(*new_pr));
06914          if (!new_pr) {
06915             ast_log(LOG_ERROR, "Memory allocation error when copying penalty rules! Aborting!\n");
06916             break;
06917          }
06918          new_pr->time = pr_iter->time;
06919          new_pr->max_value = pr_iter->max_value;
06920          new_pr->min_value = pr_iter->min_value;
06921          new_pr->max_relative = pr_iter->max_relative;
06922          new_pr->min_relative = pr_iter->min_relative;
06923          AST_LIST_INSERT_TAIL(&qe->qe_rules, new_pr, list);
06924       }
06925    }
06926    AST_LIST_UNLOCK(&rule_lists);
06927 }
06928 
06929 /*!\brief The starting point for all queue calls
06930  *
06931  * The process involved here is to
06932  * 1. Parse the options specified in the call to Queue()
06933  * 2. Join the queue
06934  * 3. Wait in a loop until it is our turn to try calling a queue member
06935  * 4. Attempt to call a queue member
06936  * 5. If 4. did not result in a bridged call, then check for between
06937  *    call options such as periodic announcements etc.
06938  * 6. Try 4 again unless some condition (such as an expiration time) causes us to
06939  *    exit the queue.
06940  */
06941 static int queue_exec(struct ast_channel *chan, const char *data)
06942 {
06943    int res=-1;
06944    int ringing=0;
06945    const char *user_priority;
06946    const char *max_penalty_str;
06947    const char *min_penalty_str;
06948    int prio;
06949    int qcontinue = 0;
06950    int max_penalty, min_penalty;
06951    enum queue_result reason = QUEUE_UNKNOWN;
06952    /* whether to exit Queue application after the timeout hits */
06953    int tries = 0;
06954    int noption = 0;
06955    char *parse;
06956    int makeannouncement = 0;
06957    int position = 0;
06958    AST_DECLARE_APP_ARGS(args,
06959       AST_APP_ARG(queuename);
06960       AST_APP_ARG(options);
06961       AST_APP_ARG(url);
06962       AST_APP_ARG(announceoverride);
06963       AST_APP_ARG(queuetimeoutstr);
06964       AST_APP_ARG(agi);
06965       AST_APP_ARG(macro);
06966       AST_APP_ARG(gosub);
06967       AST_APP_ARG(rule);
06968       AST_APP_ARG(position);
06969    );
06970    /* Our queue entry */
06971    struct queue_ent qe = { 0 };
06972    struct ast_flags opts = { 0, };
06973    char *opt_args[OPT_ARG_ARRAY_SIZE];
06974 
06975    if (ast_strlen_zero(data)) {
06976       ast_log(LOG_WARNING, "Queue requires an argument: queuename[,options[,URL[,announceoverride[,timeout[,agi[,macro[,gosub[,rule[,position]]]]]]]]]\n");
06977       return -1;
06978    }
06979 
06980    parse = ast_strdupa(data);
06981    AST_STANDARD_APP_ARGS(args, parse);
06982 
06983    ast_debug(1, "queue: %s, options: %s, url: %s, announce: %s, timeout: %s, agi: %s, macro: %s, gosub: %s, rule: %s, position: %s\n",
06984       args.queuename,
06985       S_OR(args.options, ""),
06986       S_OR(args.url, ""),
06987       S_OR(args.announceoverride, ""),
06988       S_OR(args.queuetimeoutstr, ""),
06989       S_OR(args.agi, ""),
06990       S_OR(args.macro, ""),
06991       S_OR(args.gosub, ""),
06992       S_OR(args.rule, ""),
06993       S_OR(args.position, ""));
06994 
06995    if (!ast_strlen_zero(args.options)) {
06996       ast_app_parse_options(queue_exec_options, &opts, opt_args, args.options);
06997    }
06998 
06999    /* Setup our queue entry */
07000    qe.start = time(NULL);
07001 
07002    /* set the expire time based on the supplied timeout; */
07003    if (!ast_strlen_zero(args.queuetimeoutstr)) {
07004       qe.expire = qe.start + atoi(args.queuetimeoutstr);
07005    } else {
07006       qe.expire = 0;
07007    }
07008 
07009    /* Get the priority from the variable ${QUEUE_PRIO} */
07010    ast_channel_lock(chan);
07011    user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO");
07012    if (user_priority) {
07013       if (sscanf(user_priority, "%30d", &prio) == 1) {
07014          ast_debug(1, "%s: Got priority %d from ${QUEUE_PRIO}.\n", ast_channel_name(chan), prio);
07015       } else {
07016          ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
07017             user_priority, ast_channel_name(chan));
07018          prio = 0;
07019       }
07020    } else {
07021       ast_debug(3, "NO QUEUE_PRIO variable found. Using default.\n");
07022       prio = 0;
07023    }
07024 
07025    /* Get the maximum penalty from the variable ${QUEUE_MAX_PENALTY} */
07026 
07027    if ((max_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MAX_PENALTY"))) {
07028       if (sscanf(max_penalty_str, "%30d", &max_penalty) == 1) {
07029          ast_debug(1, "%s: Got max penalty %d from ${QUEUE_MAX_PENALTY}.\n", ast_channel_name(chan), max_penalty);
07030       } else {
07031          ast_log(LOG_WARNING, "${QUEUE_MAX_PENALTY}: Invalid value (%s), channel %s.\n",
07032             max_penalty_str, ast_channel_name(chan));
07033          max_penalty = INT_MAX;
07034       }
07035    } else {
07036       max_penalty = INT_MAX;
07037    }
07038 
07039    if ((min_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MIN_PENALTY"))) {
07040       if (sscanf(min_penalty_str, "%30d", &min_penalty) == 1) {
07041          ast_debug(1, "%s: Got min penalty %d from ${QUEUE_MIN_PENALTY}.\n", ast_channel_name(chan), min_penalty);
07042       } else {
07043          ast_log(LOG_WARNING, "${QUEUE_MIN_PENALTY}: Invalid value (%s), channel %s.\n",
07044             min_penalty_str, ast_channel_name(chan));
07045          min_penalty = INT_MAX;
07046       }
07047    } else {
07048       min_penalty = INT_MAX;
07049    }
07050    ast_channel_unlock(chan);
07051 
07052    if (ast_test_flag(&opts, OPT_RINGING)) {
07053       ringing = 1;
07054    }
07055 
07056    if (ringing != 1 && ast_test_flag(&opts, OPT_RING_WHEN_RINGING)) {
07057       qe.ring_when_ringing = 1;
07058    }
07059 
07060    if (ast_test_flag(&opts, OPT_GO_ON)) {
07061       qcontinue = 1;
07062    }
07063 
07064    if (args.position) {
07065       position = atoi(args.position);
07066       if (position < 0) {
07067          ast_log(LOG_WARNING, "Invalid position '%s' given for call to queue '%s'. Assuming no preference for position\n", args.position, args.queuename);
07068          position = 0;
07069       }
07070    }
07071 
07072    ast_debug(1, "queue: %s, expires: %ld, priority: %d\n",
07073       args.queuename, (long)qe.expire, prio);
07074 
07075    qe.chan = chan;
07076    qe.prio = prio;
07077    qe.max_penalty = max_penalty;
07078    qe.min_penalty = min_penalty;
07079    qe.last_pos_said = 0;
07080    qe.last_pos = 0;
07081    qe.last_periodic_announce_time = time(NULL);
07082    qe.last_periodic_announce_sound = 0;
07083    qe.valid_digits = 0;
07084    if (join_queue(args.queuename, &qe, &reason, position)) {
07085       ast_log(LOG_WARNING, "Unable to join queue '%s'\n", args.queuename);
07086       set_queue_result(chan, reason);
07087       return 0;
07088    }
07089    ast_assert(qe.parent != NULL);
07090 
07091    ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "ENTERQUEUE", "%s|%s|%d",
07092       S_OR(args.url, ""),
07093       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
07094       qe.opos);
07095    copy_rules(&qe, args.rule);
07096    qe.pr = AST_LIST_FIRST(&qe.qe_rules);
07097 check_turns:
07098    if (ringing) {
07099       ast_indicate(chan, AST_CONTROL_RINGING);
07100    } else {
07101       ast_moh_start(chan, qe.moh, NULL);
07102    }
07103 
07104    /* This is the wait loop for callers 2 through maxlen */
07105    res = wait_our_turn(&qe, ringing, &reason);
07106    if (res) {
07107       goto stop;
07108    }
07109 
07110    makeannouncement = 0;
07111 
07112    for (;;) {
07113       /* This is the wait loop for the head caller*/
07114       /* To exit, they may get their call answered; */
07115       /* they may dial a digit from the queue context; */
07116       /* or, they may timeout. */
07117 
07118       /* Leave if we have exceeded our queuetimeout */
07119       if (qe.expire && (time(NULL) >= qe.expire)) {
07120          record_abandoned(&qe);
07121          reason = QUEUE_TIMEOUT;
07122          res = 0;
07123          ast_queue_log(args.queuename, ast_channel_uniqueid(chan),"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld",
07124             qe.pos, qe.opos, (long) time(NULL) - qe.start);
07125          break;
07126       }
07127 
07128       if (makeannouncement) {
07129          /* Make a position announcement, if enabled */
07130          if (qe.parent->announcefrequency)
07131             if ((res = say_position(&qe,ringing)))
07132                goto stop;
07133       }
07134       makeannouncement = 1;
07135 
07136       /* Make a periodic announcement, if enabled */
07137       if (qe.parent->periodicannouncefrequency) {
07138          if ((res = say_periodic_announcement(&qe,ringing))) {
07139             goto stop;
07140          }
07141       }
07142 
07143       /* Leave if we have exceeded our queuetimeout */
07144       if (qe.expire && (time(NULL) >= qe.expire)) {
07145          record_abandoned(&qe);
07146          reason = QUEUE_TIMEOUT;
07147          res = 0;
07148          ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
07149          break;
07150       }
07151 
07152       /* see if we need to move to the next penalty level for this queue */
07153       while (qe.pr && ((time(NULL) - qe.start) > qe.pr->time)) {
07154          update_qe_rule(&qe);
07155       }
07156 
07157       /* Try calling all queue members for 'timeout' seconds */
07158       res = try_calling(&qe, opts, opt_args, args.announceoverride, args.url, &tries, &noption, args.agi, args.macro, args.gosub, ringing);
07159       if (res) {
07160          goto stop;
07161       }
07162 
07163       if (qe.parent->leavewhenempty) {
07164          int status = 0;
07165          if ((status = get_member_status(qe.parent, qe.max_penalty, qe.min_penalty, qe.parent->leavewhenempty))) {
07166             record_abandoned(&qe);
07167             reason = QUEUE_LEAVEEMPTY;
07168             ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe.pos, qe.opos, (long)(time(NULL) - qe.start));
07169             res = 0;
07170             break;
07171          }
07172       }
07173 
07174       /* exit after 'timeout' cycle if 'n' option enabled */
07175       if (noption && tries >= ao2_container_count(qe.parent->members)) {
07176          ast_verb(3, "Exiting on time-out cycle\n");
07177          ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
07178          record_abandoned(&qe);
07179          reason = QUEUE_TIMEOUT;
07180          res = 0;
07181          break;
07182       }
07183 
07184 
07185       /* Leave if we have exceeded our queuetimeout */
07186       if (qe.expire && (time(NULL) >= qe.expire)) {
07187          record_abandoned(&qe);
07188          reason = QUEUE_TIMEOUT;
07189          res = 0;
07190          ast_queue_log(qe.parent->name, ast_channel_uniqueid(qe.chan),"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld", qe.pos, qe.opos, (long) time(NULL) - qe.start);
07191          break;
07192       }
07193 
07194       /* If using dynamic realtime members, we should regenerate the member list for this queue */
07195       update_realtime_members(qe.parent);
07196       /* OK, we didn't get anybody; wait for 'retry' seconds; may get a digit to exit with */
07197       res = wait_a_bit(&qe);
07198       if (res) {
07199          goto stop;
07200       }
07201 
07202       /* Since this is a priority queue and
07203        * it is not sure that we are still at the head
07204        * of the queue, go and check for our turn again.
07205        */
07206       if (!is_our_turn(&qe)) {
07207          ast_debug(1, "Darn priorities, going back in queue (%s)!\n", ast_channel_name(qe.chan));
07208          goto check_turns;
07209       }
07210    }
07211 
07212 stop:
07213    if (res) {
07214       if (res < 0) {
07215          if (!qe.handled) {
07216             record_abandoned(&qe);
07217             ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "ABANDON",
07218                "%d|%d|%ld", qe.pos, qe.opos,
07219                (long) time(NULL) - qe.start);
07220             res = -1;
07221          } else if (qcontinue) {
07222             reason = QUEUE_CONTINUE;
07223             res = 0;
07224          }
07225       } else if (qe.valid_digits) {
07226          ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITWITHKEY",
07227             "%s|%d|%d|%ld", qe.digits, qe.pos, qe.opos, (long) time(NULL) - qe.start);
07228       }
07229    }
07230 
07231    /* Don't allow return code > 0 */
07232    if (res >= 0) {
07233       res = 0;
07234       if (ringing) {
07235          ast_indicate(chan, -1);
07236       } else {
07237          ast_moh_stop(chan);
07238       }
07239       ast_stopstream(chan);
07240    }
07241 
07242    set_queue_variables(qe.parent, qe.chan);
07243 
07244    leave_queue(&qe);
07245    if (reason != QUEUE_UNKNOWN)
07246       set_queue_result(chan, reason);
07247 
07248    /*
07249     * every queue_ent is given a reference to it's parent
07250     * call_queue when it joins the queue.  This ref must be taken
07251     * away right before the queue_ent is destroyed.  In this case
07252     * the queue_ent is about to be returned on the stack
07253     */
07254    qe.parent = queue_unref(qe.parent);
07255 
07256    return res;
07257 }
07258 
07259 /*!
07260  * \brief create interface var with all queue details.
07261  * \retval 0 on success
07262  * \retval -1 on error
07263 */
07264 static int queue_function_var(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
07265 {
07266    int res = -1;
07267    struct call_queue *q, tmpq = {
07268       .name = data,
07269    };
07270 
07271    char interfacevar[256] = "";
07272    float sl = 0;
07273 
07274    if (ast_strlen_zero(data)) {
07275       ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
07276       return -1;
07277    }
07278 
07279    if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE() function"))) {
07280       ao2_lock(q);
07281       if (q->setqueuevar) {
07282          sl = 0;
07283          res = 0;
07284 
07285          if (q->callscompleted > 0) {
07286             sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
07287          }
07288 
07289          snprintf(interfacevar, sizeof(interfacevar),
07290             "QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
07291             q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned,  q->servicelevel, sl);
07292 
07293          pbx_builtin_setvar_multiple(chan, interfacevar);
07294       }
07295 
07296       ao2_unlock(q);
07297       queue_t_unref(q, "Done with QUEUE() function");
07298    } else {
07299       ast_log(LOG_WARNING, "queue %s was not found\n", data);
07300    }
07301 
07302    snprintf(buf, len, "%d", res);
07303 
07304    return 0;
07305 }
07306 
07307 /*!
07308  * \brief Check if a given queue exists
07309  *
07310  */
07311 static int queue_function_exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
07312 {
07313    struct call_queue *q;
07314 
07315    buf[0] = '\0';
07316 
07317    if (ast_strlen_zero(data)) {
07318       ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
07319       return -1;
07320    }
07321    q = find_load_queue_rt_friendly(data);
07322    snprintf(buf, len, "%d", q != NULL? 1 : 0);
07323    if (q) {
07324       queue_t_unref(q, "Done with temporary reference in QUEUE_EXISTS()");
07325    }
07326 
07327    return 0;
07328 }
07329 
07330 /*!
07331  * \brief Get number either busy / free / ready or total members of a specific queue
07332  * \brief Get or set member properties penalty / paused / ringinuse
07333  * \retval number of members (busy / free / ready / total) or member info (penalty / paused / ringinuse)
07334  * \retval -1 on error
07335 */
07336 static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
07337 {
07338    int count = 0;
07339    struct member *m;
07340    struct ao2_iterator mem_iter;
07341    struct call_queue *q;
07342 
07343    AST_DECLARE_APP_ARGS(args,
07344       AST_APP_ARG(queuename);
07345       AST_APP_ARG(option);
07346       AST_APP_ARG(interface);
07347    );
07348    /* Make sure the returned value on error is zero length string. */
07349    buf[0] = '\0';
07350 
07351    if (ast_strlen_zero(data)) {
07352       ast_log(LOG_ERROR, "Missing required argument. %s(<queuename>,<option>[<interface>])\n", cmd);
07353       return -1;
07354    }
07355 
07356    AST_STANDARD_APP_ARGS(args, data);
07357 
07358    if (args.argc < 2) {
07359       ast_log(LOG_ERROR, "Missing required argument. %s(<queuename>,<option>[<interface>])\n", cmd);
07360       return -1;
07361    }
07362 
07363    if ((q = find_load_queue_rt_friendly(args.queuename))) {
07364       ao2_lock(q);
07365       if (!strcasecmp(args.option, "logged")) {
07366          mem_iter = ao2_iterator_init(q->members, 0);
07367          while ((m = ao2_iterator_next(&mem_iter))) {
07368             /* Count the agents who are logged in and presently answering calls */
07369             if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
07370                count++;
07371             }
07372             ao2_ref(m, -1);
07373          }
07374          ao2_iterator_destroy(&mem_iter);
07375       } else if (!strcasecmp(args.option, "free")) {
07376          mem_iter = ao2_iterator_init(q->members, 0);
07377          while ((m = ao2_iterator_next(&mem_iter))) {
07378             /* Count the agents who are logged in and presently answering calls */
07379             if ((m->status == AST_DEVICE_NOT_INUSE) && (!m->paused)) {
07380                count++;
07381             }
07382             ao2_ref(m, -1);
07383          }
07384          ao2_iterator_destroy(&mem_iter);
07385       } else if (!strcasecmp(args.option, "ready")) {
07386          time_t now;
07387          time(&now);
07388          mem_iter = ao2_iterator_init(q->members, 0);
07389          while ((m = ao2_iterator_next(&mem_iter))) {
07390             /* Count the agents who are logged in, not paused and not wrapping up */
07391             if ((m->status == AST_DEVICE_NOT_INUSE) && (!m->paused) &&
07392                   !(m->lastcall && q->wrapuptime && ((now - q->wrapuptime) < m->lastcall))) {
07393                count++;
07394             }
07395             ao2_ref(m, -1);
07396          }
07397          ao2_iterator_destroy(&mem_iter);
07398       } else if (!strcasecmp(args.option, "count") || ast_strlen_zero(args.option)) {
07399          count = ao2_container_count(q->members);
07400       } else if (!strcasecmp(args.option, "penalty") && !ast_strlen_zero(args.interface) &&
07401             ((m = interface_exists(q, args.interface)))) {
07402          count = m->penalty;
07403          ao2_ref(m, -1);
07404       } else if (!strcasecmp(args.option, "paused") && !ast_strlen_zero(args.interface) &&
07405             ((m = interface_exists(q, args.interface)))) {
07406          count = m->paused;
07407          ao2_ref(m, -1);
07408       } else if ( (!strcasecmp(args.option, "ignorebusy") || !strcasecmp(args.option, "ringinuse")) &&
07409             !ast_strlen_zero(args.interface) &&
07410             ((m = interface_exists(q, args.interface)))) {
07411          count = m->ringinuse;
07412          ao2_ref(m, -1);
07413       } else if (!ast_strlen_zero(args.interface)) {
07414          ast_log(LOG_ERROR, "Queue member interface %s not in queue %s\n",
07415             args.interface, args.queuename);
07416       } else {
07417          ast_log(LOG_ERROR, "Unknown option %s provided to %s, valid values are: "
07418             "logged, free, ready, count, penalty, paused, ringinuse\n", args.option, cmd);
07419       }
07420       ao2_unlock(q);
07421       queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()");
07422    } else {
07423       ast_log(LOG_WARNING, "queue %s was not found\n", args.queuename);
07424    }
07425 
07426    snprintf(buf, len, "%d", count);
07427 
07428    return 0;
07429 }
07430 
07431 /*! \brief Dialplan function QUEUE_MEMBER() Sets the members penalty / paused / ringinuse. */
07432 static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
07433 {
07434    int memvalue;
07435    struct call_queue *q;
07436    struct member *m;
07437    char rtvalue[80];
07438 
07439    AST_DECLARE_APP_ARGS(args,
07440       AST_APP_ARG(queuename);
07441       AST_APP_ARG(option);
07442       AST_APP_ARG(interface);
07443    );
07444 
07445    if (ast_strlen_zero(data)) {
07446       ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER(<queuename>,<option>,<interface>)\n");
07447       return -1;
07448    }
07449 
07450    AST_STANDARD_APP_ARGS(args, data);
07451 
07452    if (args.argc < 3) {
07453       ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
07454       return -1;
07455    }
07456 
07457    if (ast_strlen_zero(args.interface) && ast_strlen_zero(args.option)) {
07458       ast_log (LOG_ERROR, "<interface> and <option> parameter's can't be null\n");
07459       return -1;
07460    }
07461 
07462    memvalue = atoi(value);
07463    if (!strcasecmp(args.option, "penalty")) {
07464       /* if queuename = NULL then penalty will be set for interface in all the queues.*/
07465       if (set_member_value(args.queuename, args.interface, MEMBER_PENALTY, memvalue)) {
07466          ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
07467          return -1;
07468       }
07469    } else if ((q = find_load_queue_rt_friendly(args.queuename))) {
07470       ao2_lock(q);
07471       if ((m = interface_exists(q, args.interface))) {
07472          sprintf(rtvalue, "%s",(memvalue <= 0) ? "0" : "1");
07473          if (!strcasecmp(args.option, "paused")) {
07474             if (m->realtime) {
07475                update_realtime_member_field(m, q->name, args.option, rtvalue);
07476             } else {
07477                m->paused = (memvalue <= 0) ? 0 : 1;
07478             }
07479          } else if ((!strcasecmp(args.option, "ignorebusy")) || (!strcasecmp(args.option, "ringinuse"))) {
07480             if (m->realtime) {
07481                update_realtime_member_field(m, q->name, args.option, rtvalue);
07482             } else {
07483                m->ringinuse = (memvalue <= 0) ? 0 : 1;
07484             }
07485          } else {
07486             ast_log(LOG_ERROR, "Invalid option, only penalty , paused or ringinuse/ignorebusy are valid\n");
07487             ao2_ref(m, -1);
07488             ao2_unlock(q);
07489             ao2_ref(q, -1);
07490             return -1;
07491          }
07492          ao2_ref(m, -1);
07493       } else {
07494          ao2_unlock(q);
07495          ao2_ref(q, -1);
07496          ast_log(LOG_ERROR, "Invalid interface for queue\n");
07497          return -1;
07498       }
07499       ao2_unlock(q);
07500       ao2_ref(q, -1);
07501         } else {
07502       ast_log(LOG_ERROR, "Invalid queue\n");
07503       return -1;
07504    }
07505    return 0;
07506 }
07507 
07508 /*!
07509  * \brief Get the total number of members in a specific queue (Deprecated)
07510  * \retval number of members
07511  * \retval -1 on error
07512 */
07513 static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
07514 {
07515    int count = 0;
07516    struct member *m;
07517    struct call_queue *q;
07518    struct ao2_iterator mem_iter;
07519    static int depflag = 1;
07520 
07521    if (depflag) {
07522       depflag = 0;
07523       ast_log(LOG_NOTICE, "The function QUEUE_MEMBER_COUNT has been deprecated in favor of the QUEUE_MEMBER function and will not be in further releases.\n");
07524    }
07525 
07526    if (ast_strlen_zero(data)) {
07527       ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
07528       return -1;
07529    }
07530 
07531    if ((q = find_load_queue_rt_friendly(data))) {
07532       ao2_lock(q);
07533       mem_iter = ao2_iterator_init(q->members, 0);
07534       while ((m = ao2_iterator_next(&mem_iter))) {
07535          /* Count the agents who are logged in and presently answering calls */
07536          if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
07537             count++;
07538          }
07539          ao2_ref(m, -1);
07540       }
07541       ao2_iterator_destroy(&mem_iter);
07542       ao2_unlock(q);
07543       queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER_COUNT");
07544    } else {
07545       ast_log(LOG_WARNING, "queue %s was not found\n", data);
07546    }
07547 
07548    snprintf(buf, len, "%d", count);
07549 
07550    return 0;
07551 }
07552 
07553 /*! \brief Dialplan function QUEUE_WAITING_COUNT() Get number callers waiting in a specific queue */
07554 static int queue_function_queuewaitingcount(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
07555 {
07556    int count = 0;
07557    struct call_queue *q, tmpq = {
07558       .name = data,
07559    };
07560    struct ast_variable *var = NULL;
07561 
07562    buf[0] = '\0';
07563 
07564    if (ast_strlen_zero(data)) {
07565       ast_log(LOG_ERROR, "QUEUE_WAITING_COUNT requires an argument: queuename\n");
07566       return -1;
07567    }
07568 
07569    if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_WAITING_COUNT()"))) {
07570       ao2_lock(q);
07571       count = q->count;
07572       ao2_unlock(q);
07573       queue_t_unref(q, "Done with reference in QUEUE_WAITING_COUNT()");
07574    } else if ((var = ast_load_realtime("queues", "name", data, SENTINEL))) {
07575       /* if the queue is realtime but was not found in memory, this
07576        * means that the queue had been deleted from memory since it was
07577        * "dead." This means it has a 0 waiting count
07578        */
07579       count = 0;
07580       ast_variables_destroy(var);
07581    } else {
07582       ast_log(LOG_WARNING, "queue %s was not found\n", data);
07583    }
07584 
07585    snprintf(buf, len, "%d", count);
07586 
07587    return 0;
07588 }
07589 
07590 /*! \brief Dialplan function QUEUE_MEMBER_LIST() Get list of members in a specific queue */
07591 static int queue_function_queuememberlist(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
07592 {
07593    struct call_queue *q, tmpq = {
07594       .name = data,
07595    };
07596    struct member *m;
07597 
07598    /* Ensure an otherwise empty list doesn't return garbage */
07599    buf[0] = '\0';
07600 
07601    if (ast_strlen_zero(data)) {
07602       ast_log(LOG_ERROR, "QUEUE_MEMBER_LIST requires an argument: queuename\n");
07603       return -1;
07604    }
07605 
07606    if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_MEMBER_LIST()"))) {
07607       int buflen = 0, count = 0;
07608       struct ao2_iterator mem_iter;
07609 
07610       ao2_lock(q);
07611       mem_iter = ao2_iterator_init(q->members, 0);
07612       while ((m = ao2_iterator_next(&mem_iter))) {
07613          /* strcat() is always faster than printf() */
07614          if (count++) {
07615             strncat(buf + buflen, ",", len - buflen - 1);
07616             buflen++;
07617          }
07618          strncat(buf + buflen, m->interface, len - buflen - 1);
07619          buflen += strlen(m->interface);
07620          /* Safeguard against overflow (negative length) */
07621          if (buflen >= len - 2) {
07622             ao2_ref(m, -1);
07623             ast_log(LOG_WARNING, "Truncating list\n");
07624             break;
07625          }
07626          ao2_ref(m, -1);
07627       }
07628       ao2_iterator_destroy(&mem_iter);
07629       ao2_unlock(q);
07630       queue_t_unref(q, "Done with QUEUE_MEMBER_LIST()");
07631    } else
07632       ast_log(LOG_WARNING, "queue %s was not found\n", data);
07633 
07634    /* We should already be terminated, but let's make sure. */
07635    buf[len - 1] = '\0';
07636 
07637    return 0;
07638 }
07639 
07640 /*! \brief Dialplan function QUEUE_MEMBER_PENALTY() Gets the members penalty. */
07641 static int queue_function_memberpenalty_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
07642 {
07643    int penalty;
07644    AST_DECLARE_APP_ARGS(args,
07645       AST_APP_ARG(queuename);
07646       AST_APP_ARG(interface);
07647    );
07648    /* Make sure the returned value on error is NULL. */
07649    buf[0] = '\0';
07650 
07651    if (ast_strlen_zero(data)) {
07652       ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
07653       return -1;
07654    }
07655 
07656    AST_STANDARD_APP_ARGS(args, data);
07657 
07658    if (args.argc < 2) {
07659       ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
07660       return -1;
07661    }
07662 
07663    penalty = get_member_penalty (args.queuename, args.interface);
07664 
07665    if (penalty >= 0) { /* remember that buf is already '\0' */
07666       snprintf (buf, len, "%d", penalty);
07667    }
07668 
07669    return 0;
07670 }
07671 
07672 /*! \brief Dialplan function QUEUE_MEMBER_PENALTY() Sets the members penalty. */
07673 static int queue_function_memberpenalty_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
07674 {
07675    int penalty;
07676    AST_DECLARE_APP_ARGS(args,
07677       AST_APP_ARG(queuename);
07678       AST_APP_ARG(interface);
07679    );
07680 
07681    if (ast_strlen_zero(data)) {
07682       ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
07683       return -1;
07684    }
07685 
07686    AST_STANDARD_APP_ARGS(args, data);
07687 
07688    if (args.argc < 2) {
07689       ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
07690       return -1;
07691    }
07692 
07693    penalty = atoi(value);
07694 
07695    if (ast_strlen_zero(args.interface)) {
07696       ast_log (LOG_ERROR, "<interface> parameter can't be null\n");
07697       return -1;
07698    }
07699 
07700    /* if queuename = NULL then penalty will be set for interface in all the queues. */
07701    if (set_member_value(args.queuename, args.interface, MEMBER_PENALTY, penalty)) {
07702       ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
07703       return -1;
07704    }
07705 
07706    return 0;
07707 }
07708 
07709 static struct ast_custom_function queueexists_function = {
07710    .name = "QUEUE_EXISTS",
07711    .read = queue_function_exists,
07712 };
07713 
07714 static struct ast_custom_function queuevar_function = {
07715    .name = "QUEUE_VARIABLES",
07716    .read = queue_function_var,
07717 };
07718 
07719 static struct ast_custom_function queuemembercount_function = {
07720    .name = "QUEUE_MEMBER",
07721    .read = queue_function_mem_read,
07722    .write = queue_function_mem_write,
07723 };
07724 
07725 static struct ast_custom_function queuemembercount_dep = {
07726    .name = "QUEUE_MEMBER_COUNT",
07727    .read = queue_function_qac_dep,
07728 };
07729 
07730 static struct ast_custom_function queuewaitingcount_function = {
07731    .name = "QUEUE_WAITING_COUNT",
07732    .read = queue_function_queuewaitingcount,
07733 };
07734 
07735 static struct ast_custom_function queuememberlist_function = {
07736    .name = "QUEUE_MEMBER_LIST",
07737    .read = queue_function_queuememberlist,
07738 };
07739 
07740 static struct ast_custom_function queuememberpenalty_function = {
07741    .name = "QUEUE_MEMBER_PENALTY",
07742    .read = queue_function_memberpenalty_read,
07743    .write = queue_function_memberpenalty_write,
07744 };
07745 
07746 /*! \brief Reload the rules defined in queuerules.conf
07747  *
07748  * \param reload If 1, then only process queuerules.conf if the file
07749  * has changed since the last time we inspected it.
07750  * \return Always returns AST_MODULE_LOAD_SUCCESS
07751  */
07752 static int reload_queue_rules(int reload)
07753 {
07754    struct ast_config *cfg;
07755    struct rule_list *rl_iter, *new_rl;
07756    struct penalty_rule *pr_iter;
07757    char *rulecat = NULL;
07758    struct ast_variable *rulevar = NULL;
07759    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
07760 
07761    if (!(cfg = ast_config_load("queuerules.conf", config_flags))) {
07762       ast_log(LOG_NOTICE, "No queuerules.conf file found, queues will not follow penalty rules\n");
07763       return AST_MODULE_LOAD_SUCCESS;
07764    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
07765       ast_log(LOG_NOTICE, "queuerules.conf has not changed since it was last loaded. Not taking any action.\n");
07766       return AST_MODULE_LOAD_SUCCESS;
07767    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
07768       ast_log(LOG_ERROR, "Config file queuerules.conf is in an invalid format.  Aborting.\n");
07769       return AST_MODULE_LOAD_SUCCESS;
07770    }
07771 
07772    AST_LIST_LOCK(&rule_lists);
07773    while ((rl_iter = AST_LIST_REMOVE_HEAD(&rule_lists, list))) {
07774       while ((pr_iter = AST_LIST_REMOVE_HEAD(&rl_iter->rules, list)))
07775          ast_free(pr_iter);
07776       ast_free(rl_iter);
07777    }
07778    while ((rulecat = ast_category_browse(cfg, rulecat))) {
07779       if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
07780          AST_LIST_UNLOCK(&rule_lists);
07781          ast_config_destroy(cfg);
07782          return AST_MODULE_LOAD_FAILURE;
07783       } else {
07784          ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name));
07785          AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list);
07786          for (rulevar = ast_variable_browse(cfg, rulecat); rulevar; rulevar = rulevar->next)
07787             if(!strcasecmp(rulevar->name, "penaltychange"))
07788                insert_penaltychange(new_rl->name, rulevar->value, rulevar->lineno);
07789             else
07790                ast_log(LOG_WARNING, "Don't know how to handle rule type '%s' on line %d\n", rulevar->name, rulevar->lineno);
07791       }
07792    }
07793    AST_LIST_UNLOCK(&rule_lists);
07794 
07795    ast_config_destroy(cfg);
07796 
07797    return AST_MODULE_LOAD_SUCCESS;
07798 }
07799 
07800 /*! Set the global queue parameters as defined in the "general" section of queues.conf */
07801 static void queue_set_global_params(struct ast_config *cfg)
07802 {
07803    const char *general_val = NULL;
07804    queue_persistent_members = 0;
07805    if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers"))) {
07806       queue_persistent_members = ast_true(general_val);
07807    }
07808    autofill_default = 0;
07809    if ((general_val = ast_variable_retrieve(cfg, "general", "autofill"))) {
07810       autofill_default = ast_true(general_val);
07811    }
07812    montype_default = 0;
07813    if ((general_val = ast_variable_retrieve(cfg, "general", "monitor-type"))) {
07814       if (!strcasecmp(general_val, "mixmonitor"))
07815          montype_default = 1;
07816    }
07817    update_cdr = 0;
07818    if ((general_val = ast_variable_retrieve(cfg, "general", "updatecdr"))) {
07819       update_cdr = ast_true(general_val);
07820    }
07821    shared_lastcall = 0;
07822    if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall"))) {
07823       shared_lastcall = ast_true(general_val);
07824    }
07825    negative_penalty_invalid = 0;
07826    if ((general_val = ast_variable_retrieve(cfg, "general", "negative_penalty_invalid"))) {
07827       negative_penalty_invalid = ast_true(general_val);
07828    }
07829    log_membername_as_agent = 0;
07830    if ((general_val = ast_variable_retrieve(cfg, "general", "log_membername_as_agent"))) {
07831       log_membername_as_agent = ast_true(general_val);
07832    }
07833 }
07834 
07835 /*! \brief reload information pertaining to a single member
07836  *
07837  * This function is called when a member = line is encountered in
07838  * queues.conf.
07839  *
07840  * \param memberdata The part after member = in the config file
07841  * \param q The queue to which this member belongs
07842  */
07843 static void reload_single_member(const char *memberdata, struct call_queue *q)
07844 {
07845    char *membername, *interface, *state_interface, *tmp;
07846    char *parse;
07847    struct member *cur, *newm;
07848    struct member tmpmem;
07849    int penalty;
07850    int ringinuse;
07851    AST_DECLARE_APP_ARGS(args,
07852       AST_APP_ARG(interface);
07853       AST_APP_ARG(penalty);
07854       AST_APP_ARG(membername);
07855       AST_APP_ARG(state_interface);
07856       AST_APP_ARG(ringinuse);
07857    );
07858 
07859    if (ast_strlen_zero(memberdata)) {
07860       ast_log(LOG_WARNING, "Empty queue member definition. Moving on!\n");
07861       return;
07862    }
07863 
07864    /* Add a new member */
07865    parse = ast_strdupa(memberdata);
07866 
07867    AST_STANDARD_APP_ARGS(args, parse);
07868 
07869    interface = args.interface;
07870    if (!ast_strlen_zero(args.penalty)) {
07871       tmp = args.penalty;
07872       ast_strip(tmp);
07873       penalty = atoi(tmp);
07874       if (penalty < 0) {
07875          penalty = 0;
07876       }
07877    } else {
07878       penalty = 0;
07879    }
07880 
07881    if (!ast_strlen_zero(args.membername)) {
07882       membername = args.membername;
07883       ast_strip(membername);
07884    } else {
07885       membername = interface;
07886    }
07887 
07888    if (!ast_strlen_zero(args.state_interface)) {
07889       state_interface = args.state_interface;
07890       ast_strip(state_interface);
07891    } else {
07892       state_interface = interface;
07893    }
07894 
07895    if (!ast_strlen_zero(args.ringinuse)) {
07896       tmp = args.ringinuse;
07897       ast_strip(tmp);
07898       if (ast_true(tmp)) {
07899          ringinuse = 1;
07900       } else if (ast_false(tmp)) {
07901          ringinuse = 0;
07902       } else {
07903          ast_log(LOG_ERROR, "Member %s has an invalid ringinuse value. Using %s ringinuse value.\n",
07904             membername, q->name);
07905          ringinuse = q->ringinuse;
07906       }
07907    } else {
07908       ringinuse = q->ringinuse;
07909    }
07910 
07911    /* Find the old position in the list */
07912    ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
07913    cur = ao2_find(q->members, &tmpmem, OBJ_POINTER);
07914 
07915    if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface, ringinuse))) {
07916       if (cur) {
07917          /* Round Robin Queue Position must be copied if this is replacing an existing member */
07918          ao2_lock(q->members);
07919          newm->queuepos = cur->queuepos;
07920          ao2_link(q->members, newm);
07921          ao2_unlink(q->members, cur);
07922          ao2_unlock(q->members);
07923       } else {
07924          /* Otherwise we need to add using the function that will apply a round robin queue position manually. */
07925          member_add_to_queue(q, newm);
07926       }
07927       ao2_ref(newm, -1);
07928    }
07929    newm = NULL;
07930 
07931    if (cur) {
07932       ao2_ref(cur, -1);
07933    }
07934 }
07935 
07936 static int mark_member_dead(void *obj, void *arg, int flags)
07937 {
07938    struct member *member = obj;
07939    if (!member->dynamic) {
07940       member->delme = 1;
07941    }
07942    return 0;
07943 }
07944 
07945 static int kill_dead_members(void *obj, void *arg, int flags)
07946 {
07947    struct member *member = obj;
07948 
07949    if (!member->delme) {
07950       member->status = get_queue_member_status(member);
07951       return 0;
07952    } else {
07953       return CMP_MATCH;
07954    }
07955 }
07956 
07957 /*! \brief Reload information pertaining to a particular queue
07958  *
07959  * Once we have isolated a queue within reload_queues, we call this. This will either
07960  * reload information for the queue or if we're just reloading member information, we'll just
07961  * reload that without touching other settings within the queue
07962  *
07963  * \param cfg The configuration which we are reading
07964  * \param mask Tells us what information we need to reload
07965  * \param queuename The name of the queue we are reloading information from
07966  * \retval void
07967  */
07968 static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask, const char *queuename)
07969 {
07970    int new;
07971    struct call_queue *q = NULL;
07972    /*We're defining a queue*/
07973    struct call_queue tmpq = {
07974       .name = queuename,
07975    };
07976    const char *tmpvar;
07977    const int queue_reload = ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS);
07978    const int member_reload = ast_test_flag(mask, QUEUE_RELOAD_MEMBER);
07979    int prev_weight = 0;
07980    struct ast_variable *var;
07981    if (!(q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find queue for reload"))) {
07982       if (queue_reload) {
07983          /* Make one then */
07984          if (!(q = alloc_queue(queuename))) {
07985             return;
07986          }
07987       } else {
07988          /* Since we're not reloading queues, this means that we found a queue
07989           * in the configuration file which we don't know about yet. Just return.
07990           */
07991          return;
07992       }
07993       new = 1;
07994    } else {
07995       new = 0;
07996    }
07997 
07998    if (!new) {
07999       ao2_lock(q);
08000       prev_weight = q->weight ? 1 : 0;
08001    }
08002    /* Check if we already found a queue with this name in the config file */
08003    if (q->found) {
08004       ast_log(LOG_WARNING, "Queue '%s' already defined! Skipping!\n", queuename);
08005       if (!new) {
08006          /* It should be impossible to *not* hit this case*/
08007          ao2_unlock(q);
08008       }
08009       queue_t_unref(q, "We exist! Expiring temporary pointer");
08010       return;
08011    }
08012    /* Due to the fact that the "linear" strategy will have a different allocation
08013     * scheme for queue members, we must devise the queue's strategy before other initializations.
08014     * To be specific, the linear strategy needs to function like a linked list, meaning the ao2
08015     * container used will have only a single bucket instead of the typical number.
08016     */
08017    if (queue_reload) {
08018       if ((tmpvar = ast_variable_retrieve(cfg, queuename, "strategy"))) {
08019          q->strategy = strat2int(tmpvar);
08020          if (q->strategy < 0) {
08021             ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
08022             tmpvar, q->name);
08023             q->strategy = QUEUE_STRATEGY_RINGALL;
08024          }
08025       } else {
08026          q->strategy = QUEUE_STRATEGY_RINGALL;
08027       }
08028       init_queue(q);
08029    }
08030    if (member_reload) {
08031       ao2_callback(q->members, OBJ_NODATA, mark_member_dead, NULL);
08032       q->found = 1;
08033    }
08034 
08035    /* On the first pass we just read the parameters of the queue */
08036    for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
08037       if (queue_reload && strcasecmp(var->name, "member")) {
08038          queue_set_param(q, var->name, var->value, var->lineno, 1);
08039       }
08040    }
08041 
08042    /* On the second pass, we read members */
08043    for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
08044       if (member_reload && !strcasecmp(var->name, "member")) {
08045          reload_single_member(var->value, q);
08046       }
08047    }
08048 
08049    /* At this point, we've determined if the queue has a weight, so update use_weight
08050     * as appropriate
08051     */
08052    if (!q->weight && prev_weight) {
08053       ast_atomic_fetchadd_int(&use_weight, -1);
08054    } else if (q->weight && !prev_weight) {
08055       ast_atomic_fetchadd_int(&use_weight, +1);
08056    }
08057 
08058    /* Free remaining members marked as delme */
08059    if (member_reload) {
08060       ao2_lock(q->members);
08061       ao2_callback(q->members, OBJ_NODATA | OBJ_MULTIPLE, queue_delme_members_decrement_followers, q);
08062       ao2_callback(q->members, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, kill_dead_members, q);
08063       ao2_unlock(q->members);
08064    }
08065 
08066    if (new) {
08067       queues_t_link(queues, q, "Add queue to container");
08068    } else {
08069       ao2_unlock(q);
08070    }
08071    queue_t_unref(q, "Expiring creation reference");
08072 }
08073 
08074 static int remove_members_and_mark_unfound(void *obj, void *arg, int flags)
08075 {
08076    struct call_queue *q = obj;
08077    char *queuename = arg;
08078    if (!q->realtime && (ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name))) {
08079       q->found = 0;
08080 
08081    }
08082    return 0;
08083 }
08084 
08085 static int mark_dead_and_unfound(void *obj, void *arg, int flags)
08086 {
08087    struct call_queue *q = obj;
08088    char *queuename = arg;
08089    if (!q->realtime && (ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name))) {
08090       q->dead = 1;
08091       q->found = 0;
08092    }
08093    return 0;
08094 }
08095 
08096 static int kill_dead_queues(void *obj, void *arg, int flags)
08097 {
08098    struct call_queue *q = obj;
08099    char *queuename = arg;
08100    if ((ast_strlen_zero(queuename) || !strcasecmp(queuename, q->name)) && q->dead) {
08101       return CMP_MATCH;
08102    } else {
08103       return 0;
08104    }
08105 }
08106 
08107 /*! \brief reload the queues.conf file
08108  *
08109  * This function reloads the information in the general section of the queues.conf
08110  * file and potentially more, depending on the value of mask.
08111  *
08112  * \param reload 0 if we are calling this the first time, 1 every other time
08113  * \param mask Gives flags telling us what information to actually reload
08114  * \param queuename If set to a non-zero string, then only reload information from
08115  * that particular queue. Otherwise inspect all queues
08116  * \retval -1 Failure occurred
08117  * \retval 0 All clear!
08118  */
08119 static int reload_queues(int reload, struct ast_flags *mask, const char *queuename)
08120 {
08121    struct ast_config *cfg;
08122    char *cat;
08123    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
08124    const int queue_reload = ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS);
08125    const int member_reload = ast_test_flag(mask, QUEUE_RELOAD_MEMBER);
08126 
08127    if (!(cfg = ast_config_load("queues.conf", config_flags))) {
08128       ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n");
08129       return -1;
08130    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
08131       return 0;
08132    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
08133       ast_log(LOG_ERROR, "Config file queues.conf is in an invalid format.  Aborting.\n");
08134       return -1;
08135    }
08136 
08137    /* We've made it here, so it looks like we're doing operations on all queues. */
08138    ao2_lock(queues);
08139 
08140    /* Mark all queues as dead for the moment if we're reloading queues.
08141     * For clarity, we could just be reloading members, in which case we don't want to mess
08142     * with the other queue parameters at all*/
08143    if (queue_reload) {
08144       ao2_callback(queues, OBJ_NODATA | OBJ_NOLOCK, mark_dead_and_unfound, (char *) queuename);
08145    }
08146 
08147    if (member_reload) {
08148       ao2_callback(queues, OBJ_NODATA, remove_members_and_mark_unfound, (char *) queuename);
08149    }
08150 
08151    /* Chug through config file */
08152    cat = NULL;
08153    while ((cat = ast_category_browse(cfg, cat)) ) {
08154       if (!strcasecmp(cat, "general") && queue_reload) {
08155          queue_set_global_params(cfg);
08156          continue;
08157       }
08158       if (ast_strlen_zero(queuename) || !strcasecmp(cat, queuename))
08159          reload_single_queue(cfg, mask, cat);
08160    }
08161 
08162    ast_config_destroy(cfg);
08163    /* Unref all the dead queues if we were reloading queues */
08164    if (queue_reload) {
08165       ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NOLOCK, kill_dead_queues, (char *) queuename);
08166    }
08167    ao2_unlock(queues);
08168    return 0;
08169 }
08170 
08171 /*! \brief Facilitates resetting statistics for a queue
08172  *
08173  * This function actually does not reset any statistics, but
08174  * rather finds a call_queue struct which corresponds to the
08175  * passed-in queue name and passes that structure to the
08176  * clear_queue function. If no queuename is passed in, then
08177  * all queues will have their statistics reset.
08178  *
08179  * \param queuename The name of the queue to reset the statistics
08180  * for. If this is NULL or zero-length, then this means to reset
08181  * the statistics for all queues
08182  * \retval void
08183  */
08184 static int clear_stats(const char *queuename)
08185 {
08186    struct call_queue *q;
08187    struct ao2_iterator queue_iter;
08188 
08189    queue_iter = ao2_iterator_init(queues, 0);
08190    while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
08191       ao2_lock(q);
08192       if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename))
08193          clear_queue(q);
08194       ao2_unlock(q);
08195       queue_t_unref(q, "Done with iterator");
08196    }
08197    ao2_iterator_destroy(&queue_iter);
08198    return 0;
08199 }
08200 
08201 /*! \brief The command center for all reload operations
08202  *
08203  * Whenever any piece of queue information is to be reloaded, this function
08204  * is called. It interprets the flags set in the mask parameter and acts
08205  * based on how they are set.
08206  *
08207  * \param reload True if we are reloading information, false if we are loading
08208  * information for the first time.
08209  * \param mask A bitmask which tells the handler what actions to take
08210  * \param queuename The name of the queue on which we wish to take action
08211  * \retval 0 All reloads were successful
08212  * \retval non-zero There was a failure
08213  */
08214 static int reload_handler(int reload, struct ast_flags *mask, const char *queuename)
08215 {
08216    int res = 0;
08217 
08218    if (ast_test_flag(mask, QUEUE_RELOAD_RULES)) {
08219       res |= reload_queue_rules(reload);
08220    }
08221    if (ast_test_flag(mask, QUEUE_RESET_STATS)) {
08222       res |= clear_stats(queuename);
08223    }
08224    if (ast_test_flag(mask, (QUEUE_RELOAD_PARAMETERS | QUEUE_RELOAD_MEMBER))) {
08225       res |= reload_queues(reload, mask, queuename);
08226    }
08227    return res;
08228 }
08229 
08230 /*! \brief direct ouput to manager or cli with proper terminator */
08231 static void do_print(struct mansession *s, int fd, const char *str)
08232 {
08233    if (s) {
08234       astman_append(s, "%s\r\n", str);
08235    } else {
08236       ast_cli(fd, "%s\n", str);
08237    }
08238 }
08239 
08240 /*!
08241  * \brief Show queue(s) status and statistics
08242  *
08243  * List the queues strategy, calls processed, members logged in,
08244  * other queue statistics such as avg hold time.
08245 */
08246 static char *__queues_show(struct mansession *s, int fd, int argc, const char * const *argv)
08247 {
08248    struct call_queue *q;
08249    struct ast_str *out = ast_str_alloca(240);
08250    int found = 0;
08251    time_t now = time(NULL);
08252    struct ao2_iterator queue_iter;
08253    struct ao2_iterator mem_iter;
08254 
08255    if (argc != 2 && argc != 3) {
08256       return CLI_SHOWUSAGE;
08257    }
08258 
08259    if (argc == 3) { /* specific queue */
08260       if ((q = find_load_queue_rt_friendly(argv[2]))) {
08261          queue_t_unref(q, "Done with temporary pointer");
08262       }
08263    } else if (ast_check_realtime("queues")) {
08264       /* This block is to find any queues which are defined in realtime but
08265        * which have not yet been added to the in-core container
08266        */
08267       struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
08268       char *queuename;
08269       if (cfg) {
08270          for (queuename = ast_category_browse(cfg, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(cfg, queuename)) {
08271             if ((q = find_load_queue_rt_friendly(queuename))) {
08272                queue_t_unref(q, "Done with temporary pointer");
08273             }
08274          }
08275          ast_config_destroy(cfg);
08276       }
08277    }
08278 
08279    ao2_lock(queues);
08280    queue_iter = ao2_iterator_init(queues, AO2_ITERATOR_DONTLOCK);
08281    while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
08282       float sl;
08283       struct call_queue *realtime_queue = NULL;
08284 
08285       ao2_lock(q);
08286       /* This check is to make sure we don't print information for realtime
08287        * queues which have been deleted from realtime but which have not yet
08288        * been deleted from the in-core container. Only do this if we're not
08289        * looking for a specific queue.
08290        */
08291       if (argc < 3 && q->realtime) {
08292          realtime_queue = find_load_queue_rt_friendly(q->name);
08293          if (!realtime_queue) {
08294             ao2_unlock(q);
08295             queue_t_unref(q, "Done with iterator");
08296             continue;
08297          }
08298          queue_t_unref(realtime_queue, "Queue is already in memory");
08299       }
08300 
08301       if (argc == 3 && strcasecmp(q->name, argv[2])) {
08302          ao2_unlock(q);
08303          queue_t_unref(q, "Done with iterator");
08304          continue;
08305       }
08306       found = 1;
08307 
08308       ast_str_set(&out, 0, "%s has %d calls (max ", q->name, q->count);
08309       if (q->maxlen) {
08310          ast_str_append(&out, 0, "%d", q->maxlen);
08311       } else {
08312          ast_str_append(&out, 0, "unlimited");
08313       }
08314       sl = 0;
08315       if (q->callscompleted > 0) {
08316          sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
08317       }
08318       ast_str_append(&out, 0, ") in '%s' strategy (%ds holdtime, %ds talktime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds",
08319          int2strat(q->strategy), q->holdtime, q->talktime, q->weight,
08320          q->callscompleted, q->callsabandoned,sl,q->servicelevel);
08321       do_print(s, fd, ast_str_buffer(out));
08322       if (!ao2_container_count(q->members)) {
08323          do_print(s, fd, "   No Members");
08324       } else {
08325          struct member *mem;
08326 
08327          do_print(s, fd, "   Members: ");
08328          mem_iter = ao2_iterator_init(q->members, 0);
08329          while ((mem = ao2_iterator_next(&mem_iter))) {
08330             ast_str_set(&out, 0, "      %s", mem->membername);
08331             if (strcasecmp(mem->membername, mem->interface)) {
08332                ast_str_append(&out, 0, " (%s", mem->interface);
08333                if (mem->state_interface) {
08334                   ast_str_append(&out, 0, " from %s", mem->state_interface);
08335                }
08336                ast_str_append(&out, 0, ")");
08337             }
08338             if (mem->penalty) {
08339                ast_str_append(&out, 0, " with penalty %d", mem->penalty);
08340             }
08341 
08342             ast_str_append(&out, 0, " (ringinuse %s)", mem->ringinuse ? "enabled" : "disabled");
08343 
08344             ast_str_append(&out, 0, "%s%s%s (%s)",
08345                mem->dynamic ? " (dynamic)" : "",
08346                mem->realtime ? " (realtime)" : "",
08347                mem->paused ? " (paused)" : "",
08348                ast_devstate2str(mem->status));
08349             if (mem->calls) {
08350                ast_str_append(&out, 0, " has taken %d calls (last was %ld secs ago)",
08351                   mem->calls, (long) (time(NULL) - mem->lastcall));
08352             } else {
08353                ast_str_append(&out, 0, " has taken no calls yet");
08354             }
08355             do_print(s, fd, ast_str_buffer(out));
08356             ao2_ref(mem, -1);
08357          }
08358          ao2_iterator_destroy(&mem_iter);
08359       }
08360       if (!q->head) {
08361          do_print(s, fd, "   No Callers");
08362       } else {
08363          struct queue_ent *qe;
08364          int pos = 1;
08365 
08366          do_print(s, fd, "   Callers: ");
08367          for (qe = q->head; qe; qe = qe->next) {
08368             ast_str_set(&out, 0, "      %d. %s (wait: %ld:%2.2ld, prio: %d)",
08369                pos++, ast_channel_name(qe->chan), (long) (now - qe->start) / 60,
08370                (long) (now - qe->start) % 60, qe->prio);
08371             do_print(s, fd, ast_str_buffer(out));
08372          }
08373       }
08374       do_print(s, fd, ""); /* blank line between entries */
08375       ao2_unlock(q);
08376       queue_t_unref(q, "Done with iterator"); /* Unref the iterator's reference */
08377    }
08378    ao2_iterator_destroy(&queue_iter);
08379    ao2_unlock(queues);
08380    if (!found) {
08381       if (argc == 3) {
08382          ast_str_set(&out, 0, "No such queue: %s.", argv[2]);
08383       } else {
08384          ast_str_set(&out, 0, "No queues.");
08385       }
08386       do_print(s, fd, ast_str_buffer(out));
08387    }
08388    return CLI_SUCCESS;
08389 }
08390 
08391 /*!
08392  * \brief Check if a given word is in a space-delimited list
08393  *
08394  * \param list Space delimited list of words
08395  * \param word The word used to search the list
08396  *
08397  * \note This function will not return 1 if the word is at the very end of the
08398  * list (followed immediately by a \0, not a space) since it is used for
08399  * checking tab-completion and a word at the end is still being tab-completed.
08400  *
08401  * \return Returns 1 if the word is found
08402  * \return Returns 0 if the word is not found
08403 */
08404 static int word_in_list(const char *list, const char *word) {
08405    int list_len, word_len = strlen(word);
08406    const char *find, *end_find, *end_list;
08407 
08408    /* strip whitespace from front */
08409    while(isspace(*list)) {
08410       list++;
08411    }
08412 
08413    while((find = strstr(list, word))) {
08414       /* beginning of find starts inside another word? */
08415       if (find != list && *(find - 1) != ' ') {
08416          list = find;
08417          /* strip word from front */
08418          while(!isspace(*list) && *list != '\0') {
08419             list++;
08420          }
08421          /* strip whitespace from front */
08422          while(isspace(*list)) {
08423             list++;
08424          }
08425          continue;
08426       }
08427 
08428       /* end of find ends inside another word or at very end of list? */
08429       list_len = strlen(list);
08430       end_find = find + word_len;
08431       end_list = list + list_len;
08432       if (end_find == end_list || *end_find != ' ') {
08433          list = find;
08434          /* strip word from front */
08435          while(!isspace(*list) && *list != '\0') {
08436             list++;
08437          }
08438          /* strip whitespace from front */
08439          while(isspace(*list)) {
08440             list++;
08441          }
08442          continue;
08443       }
08444 
08445       /* terminating conditions satisfied, word at beginning or separated by ' ' */
08446       return 1;
08447    }
08448 
08449    return 0;
08450 }
08451 
08452 /*!
08453  * \brief Check if a given word is in a space-delimited list
08454  *
08455  * \param line The line as typed not including the current word being completed
08456  * \param word The word currently being completed
08457  * \param pos The number of completed words in line
08458  * \param state The nth desired completion option
08459  * \param word_list_offset Offset into the line where the list of queues begins.  If non-zero, queues in the list will not be offered for further completion.
08460  *
08461  * \return Returns the queue tab-completion for the given word and state
08462 */
08463 static char *complete_queue(const char *line, const char *word, int pos, int state, ptrdiff_t word_list_offset)
08464 {
08465    struct call_queue *q;
08466    char *ret = NULL;
08467    int which = 0;
08468    int wordlen = strlen(word);
08469    struct ao2_iterator queue_iter;
08470    const char *word_list = NULL;
08471 
08472    /* for certain commands, already completed items should be left out of
08473     * the list */
08474    if (word_list_offset && strlen(line) >= word_list_offset) {
08475       word_list = line + word_list_offset;
08476    }
08477 
08478    queue_iter = ao2_iterator_init(queues, 0);
08479    while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
08480       if (!strncasecmp(word, q->name, wordlen) && ++which > state
08481          && (!word_list_offset || !word_in_list(word_list, q->name))) {
08482          ret = ast_strdup(q->name);
08483          queue_t_unref(q, "Done with iterator");
08484          break;
08485       }
08486       queue_t_unref(q, "Done with iterator");
08487    }
08488    ao2_iterator_destroy(&queue_iter);
08489 
08490    /* Pretend "rules" is at the end of the queues list in certain
08491     * circumstances since it is an alternate command that should be
08492     * tab-completable for "queue show" */
08493    if (!ret && which == state && !wordlen && !strncmp("queue show", line, 10)) {
08494       ret = ast_strdup("rules");
08495    }
08496 
08497    return ret;
08498 }
08499 
08500 static char *complete_queue_show(const char *line, const char *word, int pos, int state)
08501 {
08502    if (pos == 2) {
08503       return complete_queue(line, word, pos, state, 0);
08504    }
08505    return NULL;
08506 }
08507 
08508 static char *queue_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08509 {
08510    switch ( cmd ) {
08511    case CLI_INIT:
08512       e->command = "queue show";
08513       e->usage =
08514          "Usage: queue show\n"
08515          "       Provides summary information on a specified queue.\n";
08516       return NULL;
08517    case CLI_GENERATE:
08518       return complete_queue_show(a->line, a->word, a->pos, a->n);
08519    }
08520 
08521    return __queues_show(NULL, a->fd, a->argc, a->argv);
08522 }
08523 
08524 /*!\brief callback to display queues status in manager
08525    \addtogroup Group_AMI
08526  */
08527 static int manager_queues_show(struct mansession *s, const struct message *m)
08528 {
08529    static const char * const a[] = { "queue", "show" };
08530 
08531    __queues_show(s, -1, 2, a);
08532    astman_append(s, "\r\n\r\n"); /* Properly terminate Manager output */
08533 
08534    return RESULT_SUCCESS;
08535 }
08536 
08537 static int manager_queue_rule_show(struct mansession *s, const struct message *m)
08538 {
08539    const char *rule = astman_get_header(m, "Rule");
08540    const char *id = astman_get_header(m, "ActionID");
08541    struct rule_list *rl_iter;
08542    struct penalty_rule *pr_iter;
08543 
08544    astman_append(s, "Response: Success\r\n");
08545    if (!ast_strlen_zero(id)) {
08546       astman_append(s, "ActionID: %s\r\n", id);
08547    }
08548 
08549    AST_LIST_LOCK(&rule_lists);
08550    AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
08551       if (ast_strlen_zero(rule) || !strcasecmp(rule, rl_iter->name)) {
08552          astman_append(s, "RuleList: %s\r\n", rl_iter->name);
08553          AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
08554             astman_append(s, "Rule: %d,%s%d,%s%d\r\n", pr_iter->time, pr_iter->max_relative && pr_iter->max_value >= 0 ? "+" : "", pr_iter->max_value, pr_iter->min_relative && pr_iter->min_value >= 0 ? "+" : "", pr_iter->min_value );
08555          }
08556          if (!ast_strlen_zero(rule)) {
08557             break;
08558          }
08559       }
08560    }
08561    AST_LIST_UNLOCK(&rule_lists);
08562 
08563    /*
08564     * Two blank lines instead of one because the Response and
08565     * ActionID headers used to not be present.
08566     */
08567    astman_append(s, "\r\n\r\n");
08568 
08569    return RESULT_SUCCESS;
08570 }
08571 
08572 /*! \brief Summary of queue info via the AMI */
08573 static int manager_queues_summary(struct mansession *s, const struct message *m)
08574 {
08575    time_t now;
08576    int qmemcount = 0;
08577    int qmemavail = 0;
08578    int qchancount = 0;
08579    int qlongestholdtime = 0;
08580    const char *id = astman_get_header(m, "ActionID");
08581    const char *queuefilter = astman_get_header(m, "Queue");
08582    char idText[256] = "";
08583    struct call_queue *q;
08584    struct queue_ent *qe;
08585    struct member *mem;
08586    struct ao2_iterator queue_iter;
08587    struct ao2_iterator mem_iter;
08588 
08589    astman_send_ack(s, m, "Queue summary will follow");
08590    time(&now);
08591    if (!ast_strlen_zero(id)) {
08592       snprintf(idText, 256, "ActionID: %s\r\n", id);
08593    }
08594    queue_iter = ao2_iterator_init(queues, 0);
08595    while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
08596       ao2_lock(q);
08597 
08598       /* List queue properties */
08599       if (ast_strlen_zero(queuefilter) || !strcmp(q->name, queuefilter)) {
08600          /* Reset the necessary local variables if no queuefilter is set*/
08601          qmemcount = 0;
08602          qmemavail = 0;
08603          qchancount = 0;
08604          qlongestholdtime = 0;
08605 
08606          /* List Queue Members */
08607          mem_iter = ao2_iterator_init(q->members, 0);
08608          while ((mem = ao2_iterator_next(&mem_iter))) {
08609             if ((mem->status != AST_DEVICE_UNAVAILABLE) && (mem->status != AST_DEVICE_INVALID)) {
08610                ++qmemcount;
08611                if (member_status_available(mem->status) && !mem->paused) {
08612                   ++qmemavail;
08613                }
08614             }
08615             ao2_ref(mem, -1);
08616          }
08617          ao2_iterator_destroy(&mem_iter);
08618          for (qe = q->head; qe; qe = qe->next) {
08619             if ((now - qe->start) > qlongestholdtime) {
08620                qlongestholdtime = now - qe->start;
08621             }
08622             ++qchancount;
08623          }
08624          astman_append(s, "Event: QueueSummary\r\n"
08625             "Queue: %s\r\n"
08626             "LoggedIn: %d\r\n"
08627             "Available: %d\r\n"
08628             "Callers: %d\r\n"
08629             "HoldTime: %d\r\n"
08630             "TalkTime: %d\r\n"
08631             "LongestHoldTime: %d\r\n"
08632             "%s"
08633             "\r\n",
08634             q->name, qmemcount, qmemavail, qchancount, q->holdtime, q->talktime, qlongestholdtime, idText);
08635       }
08636       ao2_unlock(q);
08637       queue_t_unref(q, "Done with iterator");
08638    }
08639    ao2_iterator_destroy(&queue_iter);
08640    astman_append(s,
08641       "Event: QueueSummaryComplete\r\n"
08642       "%s"
08643       "\r\n", idText);
08644 
08645    return RESULT_SUCCESS;
08646 }
08647 
08648 /*! \brief Queue status info via AMI */
08649 static int manager_queues_status(struct mansession *s, const struct message *m)
08650 {
08651    time_t now;
08652    int pos;
08653    const char *id = astman_get_header(m,"ActionID");
08654    const char *queuefilter = astman_get_header(m,"Queue");
08655    const char *memberfilter = astman_get_header(m,"Member");
08656    char idText[256] = "";
08657    struct call_queue *q;
08658    struct queue_ent *qe;
08659    float sl = 0;
08660    struct member *mem;
08661    struct ao2_iterator queue_iter;
08662    struct ao2_iterator mem_iter;
08663 
08664    astman_send_ack(s, m, "Queue status will follow");
08665    time(&now);
08666    if (!ast_strlen_zero(id)) {
08667       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
08668    }
08669 
08670    queue_iter = ao2_iterator_init(queues, 0);
08671    while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
08672       ao2_lock(q);
08673 
08674       /* List queue properties */
08675       if (ast_strlen_zero(queuefilter) || !strcmp(q->name, queuefilter)) {
08676          sl = ((q->callscompleted > 0) ? 100 * ((float)q->callscompletedinsl / (float)q->callscompleted) : 0);
08677          astman_append(s, "Event: QueueParams\r\n"
08678             "Queue: %s\r\n"
08679             "Max: %d\r\n"
08680             "Strategy: %s\r\n"
08681             "Calls: %d\r\n"
08682             "Holdtime: %d\r\n"
08683             "TalkTime: %d\r\n"
08684             "Completed: %d\r\n"
08685             "Abandoned: %d\r\n"
08686             "ServiceLevel: %d\r\n"
08687             "ServicelevelPerf: %2.1f\r\n"
08688             "Weight: %d\r\n"
08689             "%s"
08690             "\r\n",
08691             q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted,
08692             q->callsabandoned, q->servicelevel, sl, q->weight, idText);
08693          /* List Queue Members */
08694          mem_iter = ao2_iterator_init(q->members, 0);
08695          while ((mem = ao2_iterator_next(&mem_iter))) {
08696             if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter) || !strcmp(mem->membername, memberfilter)) {
08697                astman_append(s, "Event: QueueMember\r\n"
08698                   "Queue: %s\r\n"
08699                   "Name: %s\r\n"
08700                   "Location: %s\r\n"
08701                   "StateInterface: %s\r\n"
08702                   "Membership: %s\r\n"
08703                   "Penalty: %d\r\n"
08704                   "CallsTaken: %d\r\n"
08705                   "LastCall: %d\r\n"
08706                   "Status: %d\r\n"
08707                   "Paused: %d\r\n"
08708                   "%s"
08709                   "\r\n",
08710                   q->name, mem->membername, mem->interface, mem->state_interface, mem->dynamic ? "dynamic" : "static",
08711                   mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
08712             }
08713             ao2_ref(mem, -1);
08714          }
08715          ao2_iterator_destroy(&mem_iter);
08716          /* List Queue Entries */
08717          pos = 1;
08718          for (qe = q->head; qe; qe = qe->next) {
08719             astman_append(s, "Event: QueueEntry\r\n"
08720                "Queue: %s\r\n"
08721                "Position: %d\r\n"
08722                "Channel: %s\r\n"
08723                "Uniqueid: %s\r\n"
08724                "CallerIDNum: %s\r\n"
08725                "CallerIDName: %s\r\n"
08726                "ConnectedLineNum: %s\r\n"
08727                "ConnectedLineName: %s\r\n"
08728                "Wait: %ld\r\n"
08729                "%s"
08730                "\r\n",
08731                q->name, pos++, ast_channel_name(qe->chan), ast_channel_uniqueid(qe->chan),
08732                S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),
08733                S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
08734                S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),
08735                S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
08736                (long) (now - qe->start), idText);
08737          }
08738       }
08739       ao2_unlock(q);
08740       queue_t_unref(q, "Done with iterator");
08741    }
08742    ao2_iterator_destroy(&queue_iter);
08743 
08744    astman_append(s,
08745       "Event: QueueStatusComplete\r\n"
08746       "%s"
08747       "\r\n",idText);
08748 
08749    return RESULT_SUCCESS;
08750 }
08751 
08752 static int manager_add_queue_member(struct mansession *s, const struct message *m)
08753 {
08754    const char *queuename, *interface, *penalty_s, *paused_s, *membername, *state_interface;
08755    int paused, penalty = 0;
08756 
08757    queuename = astman_get_header(m, "Queue");
08758    interface = astman_get_header(m, "Interface");
08759    penalty_s = astman_get_header(m, "Penalty");
08760    paused_s = astman_get_header(m, "Paused");
08761    membername = astman_get_header(m, "MemberName");
08762    state_interface = astman_get_header(m, "StateInterface");
08763 
08764    if (ast_strlen_zero(queuename)) {
08765       astman_send_error(s, m, "'Queue' not specified.");
08766       return 0;
08767    }
08768 
08769    if (ast_strlen_zero(interface)) {
08770       astman_send_error(s, m, "'Interface' not specified.");
08771       return 0;
08772    }
08773 
08774    if (ast_strlen_zero(penalty_s)) {
08775       penalty = 0;
08776    } else if (sscanf(penalty_s, "%30d", &penalty) != 1 || penalty < 0) {
08777       penalty = 0;
08778    }
08779 
08780    if (ast_strlen_zero(paused_s)) {
08781       paused = 0;
08782    } else {
08783       paused = abs(ast_true(paused_s));
08784    }
08785 
08786    switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface)) {
08787    case RES_OKAY:
08788       if (ast_strlen_zero(membername) || !log_membername_as_agent) {
08789          ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
08790       } else {
08791          ast_queue_log(queuename, "MANAGER", membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
08792       }
08793       astman_send_ack(s, m, "Added interface to queue");
08794       break;
08795    case RES_EXISTS:
08796       astman_send_error(s, m, "Unable to add interface: Already there");
08797       break;
08798    case RES_NOSUCHQUEUE:
08799       astman_send_error(s, m, "Unable to add interface to queue: No such queue");
08800       break;
08801    case RES_OUTOFMEMORY:
08802       astman_send_error(s, m, "Out of memory");
08803       break;
08804    }
08805 
08806    return 0;
08807 }
08808 
08809 static int manager_remove_queue_member(struct mansession *s, const struct message *m)
08810 {
08811    const char *queuename, *interface;
08812    struct member *mem = NULL;
08813 
08814    queuename = astman_get_header(m, "Queue");
08815    interface = astman_get_header(m, "Interface");
08816 
08817    if (ast_strlen_zero(queuename) || ast_strlen_zero(interface)) {
08818       astman_send_error(s, m, "Need 'Queue' and 'Interface' parameters.");
08819       return 0;
08820    }
08821 
08822    if (log_membername_as_agent) {
08823       mem = find_member_by_queuename_and_interface(queuename, interface);
08824    }
08825 
08826    switch (remove_from_queue(queuename, interface)) {
08827    case RES_OKAY:
08828       if (!mem || ast_strlen_zero(mem->membername)) {
08829          ast_queue_log(queuename, "MANAGER", interface, "REMOVEMEMBER", "%s", "");
08830       } else {
08831          ast_queue_log(queuename, "MANAGER", mem->membername, "REMOVEMEMBER", "%s", "");
08832       }
08833       astman_send_ack(s, m, "Removed interface from queue");
08834       break;
08835    case RES_EXISTS:
08836       astman_send_error(s, m, "Unable to remove interface: Not there");
08837       break;
08838    case RES_NOSUCHQUEUE:
08839       astman_send_error(s, m, "Unable to remove interface from queue: No such queue");
08840       break;
08841    case RES_OUTOFMEMORY:
08842       astman_send_error(s, m, "Out of memory");
08843       break;
08844    case RES_NOT_DYNAMIC:
08845       astman_send_error(s, m, "Member not dynamic");
08846       break;
08847    }
08848 
08849    if (mem) {
08850       ao2_ref(mem, -1);
08851    }
08852 
08853    return 0;
08854 }
08855 
08856 static int manager_pause_queue_member(struct mansession *s, const struct message *m)
08857 {
08858    const char *queuename, *interface, *paused_s, *reason;
08859    int paused;
08860 
08861    interface = astman_get_header(m, "Interface");
08862    paused_s = astman_get_header(m, "Paused");
08863    queuename = astman_get_header(m, "Queue");      /* Optional - if not supplied, pause the given Interface in all queues */
08864    reason = astman_get_header(m, "Reason");        /* Optional - Only used for logging purposes */
08865 
08866    if (ast_strlen_zero(interface) || ast_strlen_zero(paused_s)) {
08867       astman_send_error(s, m, "Need 'Interface' and 'Paused' parameters.");
08868       return 0;
08869    }
08870 
08871    paused = abs(ast_true(paused_s));
08872 
08873    if (set_member_paused(queuename, interface, reason, paused)) {
08874       astman_send_error(s, m, "Interface not found");
08875    } else {
08876       astman_send_ack(s, m, paused ? "Interface paused successfully" : "Interface unpaused successfully");
08877    }
08878    return 0;
08879 }
08880 
08881 static int manager_queue_log_custom(struct mansession *s, const struct message *m)
08882 {
08883    const char *queuename, *event, *message, *interface, *uniqueid;
08884 
08885    queuename = astman_get_header(m, "Queue");
08886    uniqueid = astman_get_header(m, "UniqueId");
08887    interface = astman_get_header(m, "Interface");
08888    event = astman_get_header(m, "Event");
08889    message = astman_get_header(m, "Message");
08890 
08891    if (ast_strlen_zero(queuename) || ast_strlen_zero(event)) {
08892       astman_send_error(s, m, "Need 'Queue' and 'Event' parameters.");
08893       return 0;
08894    }
08895 
08896    ast_queue_log(queuename, S_OR(uniqueid, "NONE"), interface, event, "%s", message);
08897    astman_send_ack(s, m, "Event added successfully");
08898 
08899    return 0;
08900 }
08901 
08902 static int manager_queue_reload(struct mansession *s, const struct message *m)
08903 {
08904    struct ast_flags mask = {0,};
08905    const char *queuename = NULL;
08906    int header_found = 0;
08907 
08908    queuename = astman_get_header(m, "Queue");
08909    if (!strcasecmp(S_OR(astman_get_header(m, "Members"), ""), "yes")) {
08910       ast_set_flag(&mask, QUEUE_RELOAD_MEMBER);
08911       header_found = 1;
08912    }
08913    if (!strcasecmp(S_OR(astman_get_header(m, "Rules"), ""), "yes")) {
08914       ast_set_flag(&mask, QUEUE_RELOAD_RULES);
08915       header_found = 1;
08916    }
08917    if (!strcasecmp(S_OR(astman_get_header(m, "Parameters"), ""), "yes")) {
08918       ast_set_flag(&mask, QUEUE_RELOAD_PARAMETERS);
08919       header_found = 1;
08920    }
08921 
08922    if (!header_found) {
08923       ast_set_flag(&mask, AST_FLAGS_ALL);
08924    }
08925 
08926    if (!reload_handler(1, &mask, queuename)) {
08927       astman_send_ack(s, m, "Queue reloaded successfully");
08928    } else {
08929       astman_send_error(s, m, "Error encountered while reloading queue");
08930    }
08931    return 0;
08932 }
08933 
08934 static int manager_queue_reset(struct mansession *s, const struct message *m)
08935 {
08936    const char *queuename = NULL;
08937    struct ast_flags mask = {QUEUE_RESET_STATS,};
08938 
08939    queuename = astman_get_header(m, "Queue");
08940 
08941    if (!reload_handler(1, &mask, queuename)) {
08942       astman_send_ack(s, m, "Queue stats reset successfully");
08943    } else {
08944       astman_send_error(s, m, "Error encountered while resetting queue stats");
08945    }
08946    return 0;
08947 }
08948 
08949 static char *complete_queue_add_member(const char *line, const char *word, int pos, int state)
08950 {
08951    /* 0 - queue; 1 - add; 2 - member; 3 - <interface>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty>; 8 - as; 9 - <membername> */
08952    switch (pos) {
08953    case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
08954       return NULL;
08955    case 4: /* only one possible match, "to" */
08956       return state == 0 ? ast_strdup("to") : NULL;
08957    case 5: /* <queue> */
08958       return complete_queue(line, word, pos, state, 0);
08959    case 6: /* only one possible match, "penalty" */
08960       return state == 0 ? ast_strdup("penalty") : NULL;
08961    case 7:
08962       if (state < 100) {      /* 0-99 */
08963          char *num;
08964          if ((num = ast_malloc(3))) {
08965             sprintf(num, "%d", state);
08966          }
08967          return num;
08968       } else {
08969          return NULL;
08970       }
08971    case 8: /* only one possible match, "as" */
08972       return state == 0 ? ast_strdup("as") : NULL;
08973    case 9: /* Don't attempt to complete name of member (infinite possibilities) */
08974       return NULL;
08975    default:
08976       return NULL;
08977    }
08978 }
08979 
08980 static int manager_queue_member_ringinuse(struct mansession *s, const struct message *m)
08981 {
08982    const char *queuename, *interface, *ringinuse_s;
08983    int ringinuse;
08984 
08985    interface = astman_get_header(m, "Interface");
08986    ringinuse_s = astman_get_header(m, "RingInUse");
08987 
08988    /* Optional - if not supplied, set the ringinuse value for the given Interface in all queues */
08989    queuename = astman_get_header(m, "Queue");
08990 
08991    if (ast_strlen_zero(interface) || ast_strlen_zero(ringinuse_s)) {
08992       astman_send_error(s, m, "Need 'Interface' and 'RingInUse' parameters.");
08993       return 0;
08994    }
08995 
08996    if (ast_true(ringinuse_s)) {
08997       ringinuse = 1;
08998    } else if (ast_false(ringinuse_s)) {
08999       ringinuse = 0;
09000    } else {
09001       astman_send_error(s, m, "'RingInUse' parameter must be a truth value (yes/no, on/off, 0/1, etc)");
09002       return 0;
09003    }
09004 
09005    if (set_member_value(queuename, interface, MEMBER_RINGINUSE, ringinuse)) {
09006       astman_send_error(s, m, "Invalid interface, queuename, or ringinuse value\n");
09007    } else {
09008       astman_send_ack(s, m, "Interface ringinuse set successfully");
09009    }
09010 
09011    return 0;
09012 }
09013 
09014 static int manager_queue_member_penalty(struct mansession *s, const struct message *m)
09015 {
09016    const char *queuename, *interface, *penalty_s;
09017    int penalty;
09018 
09019    interface = astman_get_header(m, "Interface");
09020    penalty_s = astman_get_header(m, "Penalty");
09021    /* Optional - if not supplied, set the penalty value for the given Interface in all queues */
09022    queuename = astman_get_header(m, "Queue");
09023 
09024    if (ast_strlen_zero(interface) || ast_strlen_zero(penalty_s)) {
09025       astman_send_error(s, m, "Need 'Interface' and 'Penalty' parameters.");
09026       return 0;
09027    }
09028 
09029    penalty = atoi(penalty_s);
09030 
09031    if (set_member_value((char *)queuename, (char *)interface, MEMBER_PENALTY, penalty)) {
09032       astman_send_error(s, m, "Invalid interface, queuename or penalty");
09033    } else {
09034       astman_send_ack(s, m, "Interface penalty set successfully");
09035    }
09036 
09037    return 0;
09038 }
09039 
09040 static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
09041 {
09042    const char *queuename, *interface, *membername = NULL, *state_interface = NULL;
09043    int penalty;
09044 
09045    switch ( cmd ) {
09046    case CLI_INIT:
09047       e->command = "queue add member";
09048       e->usage =
09049          "Usage: queue add member <dial string> to <queue> [[[penalty <penalty>] as <membername>] state_interface <interface>]\n"
09050          "       Add a dial string (Such as a channel,e.g. SIP/6001) to a queue with optionally:  a penalty, membername and a state_interface\n";
09051       return NULL;
09052    case CLI_GENERATE:
09053       return complete_queue_add_member(a->line, a->word, a->pos, a->n);
09054    }
09055 
09056    if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10) && (a->argc != 12)) {
09057       return CLI_SHOWUSAGE;
09058    } else if (strcmp(a->argv[4], "to")) {
09059       return CLI_SHOWUSAGE;
09060    } else if ((a->argc >= 8) && strcmp(a->argv[6], "penalty")) {
09061       return CLI_SHOWUSAGE;
09062    } else if ((a->argc >= 10) && strcmp(a->argv[8], "as")) {
09063       return CLI_SHOWUSAGE;
09064    } else if ((a->argc == 12) && strcmp(a->argv[10], "state_interface")) {
09065       return CLI_SHOWUSAGE;
09066    }
09067 
09068    queuename = a->argv[5];
09069    interface = a->argv[3];
09070    if (a->argc >= 8) {
09071       if (sscanf(a->argv[7], "%30d", &penalty) == 1) {
09072          if (penalty < 0) {
09073             ast_cli(a->fd, "Penalty must be >= 0\n");
09074             penalty = 0;
09075          }
09076       } else {
09077          ast_cli(a->fd, "Penalty must be an integer >= 0\n");
09078          penalty = 0;
09079       }
09080    } else {
09081       penalty = 0;
09082    }
09083 
09084    if (a->argc >= 10) {
09085       membername = a->argv[9];
09086    }
09087 
09088    if (a->argc >= 12) {
09089       state_interface = a->argv[11];
09090    }
09091 
09092    switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface)) {
09093    case RES_OKAY:
09094       if (ast_strlen_zero(membername) || !log_membername_as_agent) {
09095          ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
09096       } else {
09097          ast_queue_log(queuename, "CLI", membername, "ADDMEMBER", "%s", "");
09098       }
09099       ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
09100       return CLI_SUCCESS;
09101    case RES_EXISTS:
09102       ast_cli(a->fd, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
09103       return CLI_FAILURE;
09104    case RES_NOSUCHQUEUE:
09105       ast_cli(a->fd, "Unable to add interface to queue '%s': No such queue\n", queuename);
09106       return CLI_FAILURE;
09107    case RES_OUTOFMEMORY:
09108       ast_cli(a->fd, "Out of memory\n");
09109       return CLI_FAILURE;
09110    case RES_NOT_DYNAMIC:
09111       ast_cli(a->fd, "Member not dynamic\n");
09112       return CLI_FAILURE;
09113    default:
09114       return CLI_FAILURE;
09115    }
09116 }
09117 
09118 static char *complete_queue_remove_member(const char *line, const char *word, int pos, int state)
09119 {
09120    int which = 0;
09121    struct call_queue *q;
09122    struct member *m;
09123    struct ao2_iterator queue_iter;
09124    struct ao2_iterator mem_iter;
09125    int wordlen = strlen(word);
09126 
09127    /* 0 - queue; 1 - remove; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
09128    if (pos > 5 || pos < 3) {
09129       return NULL;
09130    }
09131    if (pos == 4) {   /* only one possible match, 'from' */
09132       return (state == 0 ? ast_strdup("from") : NULL);
09133    }
09134 
09135    if (pos == 5) {   /* No need to duplicate code */
09136       return complete_queue(line, word, pos, state, 0);
09137    }
09138 
09139    /* here is the case for 3, <member> */
09140    queue_iter = ao2_iterator_init(queues, 0);
09141    while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
09142       ao2_lock(q);
09143       mem_iter = ao2_iterator_init(q->members, 0);
09144       while ((m = ao2_iterator_next(&mem_iter))) {
09145          if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
09146             char *tmp;
09147             tmp = ast_strdup(m->interface);
09148             ao2_ref(m, -1);
09149             ao2_iterator_destroy(&mem_iter);
09150             ao2_unlock(q);
09151             queue_t_unref(q, "Done with iterator, returning interface name");
09152             ao2_iterator_destroy(&queue_iter);
09153             return tmp;
09154          }
09155          ao2_ref(m, -1);
09156       }
09157       ao2_iterator_destroy(&mem_iter);
09158       ao2_unlock(q);
09159       queue_t_unref(q, "Done with iterator");
09160    }
09161    ao2_iterator_destroy(&queue_iter);
09162 
09163    return NULL;
09164 }
09165 
09166 static char *handle_queue_remove_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
09167 {
09168    const char *queuename, *interface;
09169    struct member *mem = NULL;
09170    char *res = CLI_FAILURE;
09171 
09172    switch (cmd) {
09173    case CLI_INIT:
09174       e->command = "queue remove member";
09175       e->usage =
09176          "Usage: queue remove member <channel> from <queue>\n"
09177          "       Remove a specific channel from a queue.\n";
09178       return NULL;
09179    case CLI_GENERATE:
09180       return complete_queue_remove_member(a->line, a->word, a->pos, a->n);
09181    }
09182 
09183    if (a->argc != 6) {
09184       return CLI_SHOWUSAGE;
09185    } else if (strcmp(a->argv[4], "from")) {
09186       return CLI_SHOWUSAGE;
09187    }
09188 
09189    queuename = a->argv[5];
09190    interface = a->argv[3];
09191 
09192    if (log_membername_as_agent) {
09193       mem = find_member_by_queuename_and_interface(queuename, interface);
09194    }
09195 
09196    switch (remove_from_queue(queuename, interface)) {
09197    case RES_OKAY:
09198       if (!mem || ast_strlen_zero(mem->membername)) {
09199          ast_queue_log(queuename, "CLI", interface, "REMOVEMEMBER", "%s", "");
09200       } else {
09201          ast_queue_log(queuename, "CLI", mem->membername, "REMOVEMEMBER", "%s", "");
09202       }
09203       ast_cli(a->fd, "Removed interface %s from queue '%s'\n", interface, queuename);
09204       res = CLI_SUCCESS;
09205       break;
09206    case RES_EXISTS:
09207       ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
09208       break;
09209    case RES_NOSUCHQUEUE:
09210       ast_cli(a->fd, "Unable to remove interface from queue '%s': No such queue\n", queuename);
09211       break;
09212    case RES_OUTOFMEMORY:
09213       ast_cli(a->fd, "Out of memory\n");
09214       break;
09215    case RES_NOT_DYNAMIC:
09216       ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Member is not dynamic\n", interface, queuename);
09217       break;
09218    }
09219 
09220    if (mem) {
09221       ao2_ref(mem, -1);
09222    }
09223 
09224    return res;
09225 }
09226 
09227 static char *complete_queue_pause_member(const char *line, const char *word, int pos, int state)
09228 {
09229    /* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
09230    switch (pos) {
09231    case 3:  /* Don't attempt to complete name of interface (infinite possibilities) */
09232       return NULL;
09233    case 4:  /* only one possible match, "queue" */
09234       return state == 0 ? ast_strdup("queue") : NULL;
09235    case 5:  /* <queue> */
09236       return complete_queue(line, word, pos, state, 0);
09237    case 6: /* "reason" */
09238       return state == 0 ? ast_strdup("reason") : NULL;
09239    case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
09240       return NULL;
09241    default:
09242       return NULL;
09243    }
09244 }
09245 
09246 static char *handle_queue_pause_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
09247 {
09248    const char *queuename, *interface, *reason;
09249    int paused;
09250 
09251    switch (cmd) {
09252    case CLI_INIT:
09253       e->command = "queue {pause|unpause} member";
09254       e->usage =
09255          "Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]\n"
09256          "  Pause or unpause a queue member. Not specifying a particular queue\n"
09257          "  will pause or unpause a member across all queues to which the member\n"
09258          "  belongs.\n";
09259       return NULL;
09260    case CLI_GENERATE:
09261       return complete_queue_pause_member(a->line, a-> word, a->pos, a->n);
09262    }
09263 
09264    if (a->argc < 4 || a->argc == 5 || a->argc == 7 || a->argc > 8) {
09265       return CLI_SHOWUSAGE;
09266    } else if (a->argc >= 5 && strcmp(a->argv[4], "queue")) {
09267       return CLI_SHOWUSAGE;
09268    } else if (a->argc == 8 && strcmp(a->argv[6], "reason")) {
09269       return CLI_SHOWUSAGE;
09270    }
09271 
09272 
09273    interface = a->argv[3];
09274    queuename = a->argc >= 6 ? a->argv[5] : NULL;
09275    reason = a->argc == 8 ? a->argv[7] : NULL;
09276    paused = !strcasecmp(a->argv[1], "pause");
09277 
09278    if (set_member_paused(queuename, interface, reason, paused) == RESULT_SUCCESS) {
09279       ast_cli(a->fd, "%spaused interface '%s'", paused ? "" : "un", interface);
09280       if (!ast_strlen_zero(queuename)) {
09281          ast_cli(a->fd, " in queue '%s'", queuename);
09282       }
09283       if (!ast_strlen_zero(reason)) {
09284          ast_cli(a->fd, " for reason '%s'", reason);
09285       }
09286       ast_cli(a->fd, "\n");
09287       return CLI_SUCCESS;
09288    } else {
09289       ast_cli(a->fd, "Unable to %spause interface '%s'", paused ? "" : "un", interface);
09290       if (!ast_strlen_zero(queuename)) {
09291          ast_cli(a->fd, " in queue '%s'", queuename);
09292       }
09293       if (!ast_strlen_zero(reason)) {
09294          ast_cli(a->fd, " for reason '%s'", reason);
09295       }
09296       ast_cli(a->fd, "\n");
09297       return CLI_FAILURE;
09298    }
09299 }
09300 
09301 static char *complete_queue_set_member_value(const char *line, const char *word, int pos, int state)
09302 {
09303    /* 0 - queue; 1 - set; 2 - penalty/ringinuse; 3 - <value>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
09304    switch (pos) {
09305    case 4:
09306       if (state == 0) {
09307          return ast_strdup("on");
09308       } else {
09309          return NULL;
09310       }
09311    case 6:
09312       if (state == 0) {
09313          return ast_strdup("in");
09314       } else {
09315          return NULL;
09316       }
09317    case 7:
09318       return complete_queue(line, word, pos, state, 0);
09319    default:
09320       return NULL;
09321    }
09322 }
09323 
09324 static char *handle_queue_set_member_ringinuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
09325 {
09326    const char *queuename = NULL, *interface;
09327    int ringinuse;
09328 
09329    switch (cmd) {
09330    case CLI_INIT:
09331       e->command = "queue set ringinuse";
09332       e->usage =
09333       "Usage: queue set ringinuse <yes/no> on <interface> [in <queue>]\n"
09334       "  Set a member's ringinuse in the queue specified. If no queue is specified\n"
09335       "  then that interface's penalty is set in all queues to which that interface is a member.\n";
09336       break;
09337       return NULL;
09338    case CLI_GENERATE:
09339       return complete_queue_set_member_value(a->line, a->word, a->pos, a->n);
09340    }
09341 
09342    /* Sensible argument counts */
09343    if (a->argc != 6 && a->argc != 8) {
09344       return CLI_SHOWUSAGE;
09345    }
09346 
09347    /* Uses proper indicational words */
09348    if (strcmp(a->argv[4], "on") || (a->argc > 6 && strcmp(a->argv[6], "in"))) {
09349       return CLI_SHOWUSAGE;
09350    }
09351 
09352    /* Set the queue name if applicale */
09353    if (a->argc == 8) {
09354       queuename = a->argv[7];
09355    }
09356 
09357    /* Interface being set */
09358    interface = a->argv[5];
09359 
09360    /* Check and set the ringinuse value */
09361    if (ast_true(a->argv[3])) {
09362       ringinuse = 1;
09363    } else if (ast_false(a->argv[3])) {
09364       ringinuse = 0;
09365    } else {
09366       return CLI_SHOWUSAGE;
09367    }
09368 
09369    switch (set_member_value(queuename, interface, MEMBER_RINGINUSE, ringinuse)) {
09370    case RESULT_SUCCESS:
09371       ast_cli(a->fd, "Set ringinuse on interface '%s' from queue '%s'\n", interface, queuename);
09372       return CLI_SUCCESS;
09373    case RESULT_FAILURE:
09374       ast_cli(a->fd, "Failed to set ringinuse on interface '%s' from queue '%s'\n", interface, queuename);
09375       return CLI_FAILURE;
09376    default:
09377       return CLI_FAILURE;
09378    }
09379 }
09380 
09381 static char *handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
09382 {
09383    const char *queuename = NULL, *interface;
09384    int penalty = 0;
09385 
09386    switch (cmd) {
09387    case CLI_INIT:
09388       e->command = "queue set penalty";
09389       e->usage =
09390       "Usage: queue set penalty <penalty> on <interface> [in <queue>]\n"
09391       "  Set a member's penalty in the queue specified. If no queue is specified\n"
09392       "  then that interface's penalty is set in all queues to which that interface is a member\n";
09393       return NULL;
09394    case CLI_GENERATE:
09395       return complete_queue_set_member_value(a->line, a->word, a->pos, a->n);
09396    }
09397 
09398    if (a->argc != 6 && a->argc != 8) {
09399       return CLI_SHOWUSAGE;
09400    } else if (strcmp(a->argv[4], "on") || (a->argc > 6 && strcmp(a->argv[6], "in"))) {
09401       return CLI_SHOWUSAGE;
09402    }
09403 
09404    if (a->argc == 8) {
09405       queuename = a->argv[7];
09406    }
09407    interface = a->argv[5];
09408    penalty = atoi(a->argv[3]);
09409 
09410    switch (set_member_value(queuename, interface, MEMBER_PENALTY, penalty)) {
09411    case RESULT_SUCCESS:
09412       ast_cli(a->fd, "Set penalty on interface '%s' from queue '%s'\n", interface, queuename);
09413       return CLI_SUCCESS;
09414    case RESULT_FAILURE:
09415       ast_cli(a->fd, "Failed to set penalty on interface '%s' from queue '%s'\n", interface, queuename);
09416       return CLI_FAILURE;
09417    default:
09418       return CLI_FAILURE;
09419    }
09420 }
09421 
09422 static char *complete_queue_rule_show(const char *line, const char *word, int pos, int state)
09423 {
09424    int which = 0;
09425    struct rule_list *rl_iter;
09426    int wordlen = strlen(word);
09427    char *ret = NULL;
09428    if (pos != 3) /* Wha? */ {
09429       return NULL;
09430    }
09431 
09432    AST_LIST_LOCK(&rule_lists);
09433    AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
09434       if (!strncasecmp(word, rl_iter->name, wordlen) && ++which > state) {
09435          ret = ast_strdup(rl_iter->name);
09436          break;
09437       }
09438    }
09439    AST_LIST_UNLOCK(&rule_lists);
09440 
09441    return ret;
09442 }
09443 
09444 static char *handle_queue_rule_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
09445 {
09446    const char *rule;
09447    struct rule_list *rl_iter;
09448    struct penalty_rule *pr_iter;
09449    switch (cmd) {
09450    case CLI_INIT:
09451       e->command = "queue show rules";
09452       e->usage =
09453       "Usage: queue show rules [rulename]\n"
09454       "  Show the list of rules associated with rulename. If no\n"
09455       "  rulename is specified, list all rules defined in queuerules.conf\n";
09456       return NULL;
09457    case CLI_GENERATE:
09458       return complete_queue_rule_show(a->line, a->word, a->pos, a->n);
09459    }
09460 
09461    if (a->argc != 3 && a->argc != 4) {
09462       return CLI_SHOWUSAGE;
09463    }
09464 
09465    rule = a->argc == 4 ? a->argv[3] : "";
09466    AST_LIST_LOCK(&rule_lists);
09467    AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
09468       if (ast_strlen_zero(rule) || !strcasecmp(rl_iter->name, rule)) {
09469          ast_cli(a->fd, "Rule: %s\n", rl_iter->name);
09470          AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
09471             ast_cli(a->fd, "\tAfter %d seconds, adjust QUEUE_MAX_PENALTY %s %d and adjust QUEUE_MIN_PENALTY %s %d\n", pr_iter->time, pr_iter->max_relative ? "by" : "to", pr_iter->max_value, pr_iter->min_relative ? "by" : "to", pr_iter->min_value);
09472          }
09473       }
09474    }
09475    AST_LIST_UNLOCK(&rule_lists);
09476    return CLI_SUCCESS;
09477 }
09478 
09479 static char *handle_queue_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
09480 {
09481    struct ast_flags mask = {QUEUE_RESET_STATS,};
09482    int i;
09483 
09484    switch (cmd) {
09485       case CLI_INIT:
09486          e->command = "queue reset stats";
09487          e->usage =
09488             "Usage: queue reset stats [<queuenames>]\n"
09489             "\n"
09490             "Issuing this command will reset statistics for\n"
09491             "<queuenames>, or for all queues if no queue is\n"
09492             "specified.\n";
09493          return NULL;
09494       case CLI_GENERATE:
09495          if (a->pos >= 3) {
09496             return complete_queue(a->line, a->word, a->pos, a->n, 17);
09497          } else {
09498             return NULL;
09499          }
09500    }
09501 
09502    if (a->argc < 3) {
09503       return CLI_SHOWUSAGE;
09504    }
09505 
09506    if (a->argc == 3) {
09507       reload_handler(1, &mask, NULL);
09508       return CLI_SUCCESS;
09509    }
09510 
09511    for (i = 3; i < a->argc; ++i) {
09512       reload_handler(1, &mask, a->argv[i]);
09513    }
09514 
09515    return CLI_SUCCESS;
09516 }
09517 
09518 static char *handle_queue_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
09519 {
09520    struct ast_flags mask = {0,};
09521    int i;
09522 
09523    switch (cmd) {
09524       case CLI_INIT:
09525          e->command = "queue reload {parameters|members|rules|all}";
09526          e->usage =
09527             "Usage: queue reload {parameters|members|rules|all} [<queuenames>]\n"
09528             "Reload queues. If <queuenames> are specified, only reload information pertaining\n"
09529             "to <queuenames>. One of 'parameters,' 'members,' 'rules,' or 'all' must be\n"
09530             "specified in order to know what information to reload. Below is an explanation\n"
09531             "of each of these qualifiers.\n"
09532             "\n"
09533             "\t'members' - reload queue members from queues.conf\n"
09534             "\t'parameters' - reload all queue options except for queue members\n"
09535             "\t'rules' - reload the queuerules.conf file\n"
09536             "\t'all' - reload queue rules, parameters, and members\n"
09537             "\n"
09538             "Note: the 'rules' qualifier here cannot actually be applied to a specific queue.\n"
09539             "Use of the 'rules' qualifier causes queuerules.conf to be reloaded. Even if only\n"
09540             "one queue is specified when using this command, reloading queue rules may cause\n"
09541             "other queues to be affected\n";
09542          return NULL;
09543       case CLI_GENERATE:
09544          if (a->pos >= 3) {
09545             /* find the point at which the list of queue names starts */
09546             const char *command_end = a->line + strlen("queue reload ");
09547             command_end = strchr(command_end, ' ');
09548             if (!command_end) {
09549                command_end = a->line + strlen(a->line);
09550             }
09551             return complete_queue(a->line, a->word, a->pos, a->n, command_end - a->line);
09552          } else {
09553             return NULL;
09554          }
09555    }
09556 
09557    if (a->argc < 3)
09558       return CLI_SHOWUSAGE;
09559 
09560    if (!strcasecmp(a->argv[2], "rules")) {
09561       ast_set_flag(&mask, QUEUE_RELOAD_RULES);
09562    } else if (!strcasecmp(a->argv[2], "members")) {
09563       ast_set_flag(&mask, QUEUE_RELOAD_MEMBER);
09564    } else if (!strcasecmp(a->argv[2], "parameters")) {
09565       ast_set_flag(&mask, QUEUE_RELOAD_PARAMETERS);
09566    } else if (!strcasecmp(a->argv[2], "all")) {
09567       ast_set_flag(&mask, AST_FLAGS_ALL);
09568    }
09569 
09570    if (a->argc == 3) {
09571       reload_handler(1, &mask, NULL);
09572       return CLI_SUCCESS;
09573    }
09574 
09575    for (i = 3; i < a->argc; ++i) {
09576       reload_handler(1, &mask, a->argv[i]);
09577    }
09578 
09579    return CLI_SUCCESS;
09580 }
09581 
09582 static const char qpm_cmd_usage[] =
09583 "Usage: queue pause member <channel> in <queue> reason <reason>\n";
09584 
09585 static const char qum_cmd_usage[] =
09586 "Usage: queue unpause member <channel> in <queue> reason <reason>\n";
09587 
09588 static const char qsmp_cmd_usage[] =
09589 "Usage: queue set member penalty <channel> from <queue> <penalty>\n";
09590 
09591 static struct ast_cli_entry cli_queue[] = {
09592    AST_CLI_DEFINE(queue_show, "Show status of a specified queue"),
09593    AST_CLI_DEFINE(handle_queue_rule_show, "Show the rules defined in queuerules.conf"),
09594    AST_CLI_DEFINE(handle_queue_add_member, "Add a channel to a specified queue"),
09595    AST_CLI_DEFINE(handle_queue_remove_member, "Removes a channel from a specified queue"),
09596    AST_CLI_DEFINE(handle_queue_pause_member, "Pause or unpause a queue member"),
09597    AST_CLI_DEFINE(handle_queue_set_member_penalty, "Set penalty for a channel of a specified queue"),
09598    AST_CLI_DEFINE(handle_queue_set_member_ringinuse, "Set ringinuse for a channel of a specified queue"),
09599    AST_CLI_DEFINE(handle_queue_reload, "Reload queues, members, queue rules, or parameters"),
09600    AST_CLI_DEFINE(handle_queue_reset, "Reset statistics for a queue"),
09601 };
09602 
09603 /* struct call_queue astdata mapping. */
09604 #define DATA_EXPORT_CALL_QUEUE(MEMBER)             \
09605    MEMBER(call_queue, name, AST_DATA_STRING)       \
09606    MEMBER(call_queue, moh, AST_DATA_STRING)        \
09607    MEMBER(call_queue, announce, AST_DATA_STRING)         \
09608    MEMBER(call_queue, context, AST_DATA_STRING)       \
09609    MEMBER(call_queue, membermacro, AST_DATA_STRING)      \
09610    MEMBER(call_queue, membergosub, AST_DATA_STRING)      \
09611    MEMBER(call_queue, defaultrule, AST_DATA_STRING)      \
09612    MEMBER(call_queue, sound_next, AST_DATA_STRING)       \
09613    MEMBER(call_queue, sound_thereare, AST_DATA_STRING)      \
09614    MEMBER(call_queue, sound_calls, AST_DATA_STRING)      \
09615    MEMBER(call_queue, queue_quantity1, AST_DATA_STRING)     \
09616    MEMBER(call_queue, queue_quantity2, AST_DATA_STRING)     \
09617    MEMBER(call_queue, sound_holdtime, AST_DATA_STRING)      \
09618    MEMBER(call_queue, sound_minutes, AST_DATA_STRING)    \
09619    MEMBER(call_queue, sound_minute, AST_DATA_STRING)     \
09620    MEMBER(call_queue, sound_seconds, AST_DATA_STRING)    \
09621    MEMBER(call_queue, sound_thanks, AST_DATA_STRING)     \
09622    MEMBER(call_queue, sound_callerannounce, AST_DATA_STRING)   \
09623    MEMBER(call_queue, sound_reporthold, AST_DATA_STRING)    \
09624    MEMBER(call_queue, dead, AST_DATA_BOOLEAN)         \
09625    MEMBER(call_queue, eventwhencalled, AST_DATA_BOOLEAN)    \
09626    MEMBER(call_queue, ringinuse, AST_DATA_BOOLEAN)       \
09627    MEMBER(call_queue, announce_to_first_user, AST_DATA_BOOLEAN)   \
09628    MEMBER(call_queue, setinterfacevar, AST_DATA_BOOLEAN)    \
09629    MEMBER(call_queue, setqueuevar, AST_DATA_BOOLEAN)     \
09630    MEMBER(call_queue, setqueueentryvar, AST_DATA_BOOLEAN)      \
09631    MEMBER(call_queue, reportholdtime, AST_DATA_BOOLEAN)     \
09632    MEMBER(call_queue, wrapped, AST_DATA_BOOLEAN)         \
09633    MEMBER(call_queue, timeoutrestart, AST_DATA_BOOLEAN)     \
09634    MEMBER(call_queue, announceholdtime, AST_DATA_INTEGER)      \
09635    MEMBER(call_queue, maskmemberstatus, AST_DATA_BOOLEAN)      \
09636    MEMBER(call_queue, realtime, AST_DATA_BOOLEAN)        \
09637    MEMBER(call_queue, found, AST_DATA_BOOLEAN)        \
09638    MEMBER(call_queue, announcepositionlimit, AST_DATA_INTEGER) \
09639    MEMBER(call_queue, announcefrequency, AST_DATA_SECONDS)     \
09640    MEMBER(call_queue, minannouncefrequency, AST_DATA_SECONDS)  \
09641    MEMBER(call_queue, periodicannouncefrequency, AST_DATA_SECONDS)   \
09642    MEMBER(call_queue, numperiodicannounce, AST_DATA_INTEGER)   \
09643    MEMBER(call_queue, randomperiodicannounce, AST_DATA_INTEGER)   \
09644    MEMBER(call_queue, roundingseconds, AST_DATA_SECONDS)    \
09645    MEMBER(call_queue, holdtime, AST_DATA_SECONDS)        \
09646    MEMBER(call_queue, talktime, AST_DATA_SECONDS)        \
09647    MEMBER(call_queue, callscompleted, AST_DATA_INTEGER)     \
09648    MEMBER(call_queue, callsabandoned, AST_DATA_INTEGER)     \
09649    MEMBER(call_queue, servicelevel, AST_DATA_INTEGER)    \
09650    MEMBER(call_queue, callscompletedinsl, AST_DATA_INTEGER) \
09651    MEMBER(call_queue, monfmt, AST_DATA_STRING)        \
09652    MEMBER(call_queue, montype, AST_DATA_INTEGER)         \
09653    MEMBER(call_queue, count, AST_DATA_INTEGER)        \
09654    MEMBER(call_queue, maxlen, AST_DATA_INTEGER)       \
09655    MEMBER(call_queue, wrapuptime, AST_DATA_SECONDS)      \
09656    MEMBER(call_queue, retry, AST_DATA_SECONDS)        \
09657    MEMBER(call_queue, timeout, AST_DATA_SECONDS)         \
09658    MEMBER(call_queue, weight, AST_DATA_INTEGER)       \
09659    MEMBER(call_queue, autopause, AST_DATA_INTEGER)       \
09660    MEMBER(call_queue, timeoutpriority, AST_DATA_INTEGER)    \
09661    MEMBER(call_queue, rrpos, AST_DATA_INTEGER)        \
09662    MEMBER(call_queue, memberdelay, AST_DATA_INTEGER)     \
09663    MEMBER(call_queue, autofill, AST_DATA_INTEGER)        \
09664    MEMBER(call_queue, members, AST_DATA_CONTAINER)
09665 
09666 AST_DATA_STRUCTURE(call_queue, DATA_EXPORT_CALL_QUEUE);
09667 
09668 /* struct member astdata mapping. */
09669 #define DATA_EXPORT_MEMBER(MEMBER)              \
09670    MEMBER(member, interface, AST_DATA_STRING)         \
09671    MEMBER(member, state_interface, AST_DATA_STRING)      \
09672    MEMBER(member, membername, AST_DATA_STRING)        \
09673    MEMBER(member, penalty, AST_DATA_INTEGER)       \
09674    MEMBER(member, calls, AST_DATA_INTEGER)            \
09675    MEMBER(member, dynamic, AST_DATA_INTEGER)       \
09676    MEMBER(member, realtime, AST_DATA_INTEGER)         \
09677    MEMBER(member, status, AST_DATA_INTEGER)        \
09678    MEMBER(member, paused, AST_DATA_BOOLEAN)        \
09679    MEMBER(member, rt_uniqueid, AST_DATA_STRING)
09680 
09681 AST_DATA_STRUCTURE(member, DATA_EXPORT_MEMBER);
09682 
09683 #define DATA_EXPORT_QUEUE_ENT(MEMBER)                 \
09684    MEMBER(queue_ent, moh, AST_DATA_STRING)               \
09685    MEMBER(queue_ent, announce, AST_DATA_STRING)          \
09686    MEMBER(queue_ent, context, AST_DATA_STRING)           \
09687    MEMBER(queue_ent, digits, AST_DATA_STRING)            \
09688    MEMBER(queue_ent, valid_digits, AST_DATA_INTEGER)        \
09689    MEMBER(queue_ent, pos, AST_DATA_INTEGER)           \
09690    MEMBER(queue_ent, prio, AST_DATA_INTEGER)          \
09691    MEMBER(queue_ent, last_pos_said, AST_DATA_INTEGER)       \
09692    MEMBER(queue_ent, last_periodic_announce_time, AST_DATA_INTEGER)  \
09693    MEMBER(queue_ent, last_periodic_announce_sound, AST_DATA_INTEGER) \
09694    MEMBER(queue_ent, last_pos, AST_DATA_INTEGER)            \
09695    MEMBER(queue_ent, opos, AST_DATA_INTEGER)          \
09696    MEMBER(queue_ent, handled, AST_DATA_INTEGER)          \
09697    MEMBER(queue_ent, pending, AST_DATA_INTEGER)          \
09698    MEMBER(queue_ent, max_penalty, AST_DATA_INTEGER)         \
09699    MEMBER(queue_ent, min_penalty, AST_DATA_INTEGER)         \
09700    MEMBER(queue_ent, linpos, AST_DATA_INTEGER)           \
09701    MEMBER(queue_ent, linwrapped, AST_DATA_INTEGER)          \
09702    MEMBER(queue_ent, start, AST_DATA_INTEGER)            \
09703    MEMBER(queue_ent, expire, AST_DATA_INTEGER)           \
09704    MEMBER(queue_ent, cancel_answered_elsewhere, AST_DATA_INTEGER)
09705 
09706 AST_DATA_STRUCTURE(queue_ent, DATA_EXPORT_QUEUE_ENT);
09707 
09708 /*!
09709  * \internal
09710  * \brief Add a queue to the data_root node.
09711  * \param[in] search The search tree.
09712  * \param[in] data_root The main result node.
09713  * \param[in] queue The queue to add.
09714  */
09715 static void queues_data_provider_get_helper(const struct ast_data_search *search,
09716    struct ast_data *data_root, struct call_queue *queue)
09717 {
09718    struct ao2_iterator im;
09719    struct member *member;
09720    struct queue_ent *qe;
09721    struct ast_data *data_queue, *data_members = NULL, *enum_node;
09722    struct ast_data *data_member, *data_callers = NULL, *data_caller, *data_caller_channel;
09723 
09724    data_queue = ast_data_add_node(data_root, "queue");
09725    if (!data_queue) {
09726       return;
09727    }
09728 
09729    ast_data_add_structure(call_queue, data_queue, queue);
09730 
09731    ast_data_add_str(data_queue, "strategy", int2strat(queue->strategy));
09732    ast_data_add_int(data_queue, "membercount", ao2_container_count(queue->members));
09733 
09734    /* announce position */
09735    enum_node = ast_data_add_node(data_queue, "announceposition");
09736    if (!enum_node) {
09737       return;
09738    }
09739    switch (queue->announceposition) {
09740    case ANNOUNCEPOSITION_LIMIT:
09741       ast_data_add_str(enum_node, "text", "limit");
09742       break;
09743    case ANNOUNCEPOSITION_MORE_THAN:
09744       ast_data_add_str(enum_node, "text", "more");
09745       break;
09746    case ANNOUNCEPOSITION_YES:
09747       ast_data_add_str(enum_node, "text", "yes");
09748       break;
09749    case ANNOUNCEPOSITION_NO:
09750       ast_data_add_str(enum_node, "text", "no");
09751       break;
09752    default:
09753       ast_data_add_str(enum_node, "text", "unknown");
09754       break;
09755    }
09756    ast_data_add_int(enum_node, "value", queue->announceposition);
09757 
09758    /* add queue members */
09759    im = ao2_iterator_init(queue->members, 0);
09760    while ((member = ao2_iterator_next(&im))) {
09761       if (!data_members) {
09762          data_members = ast_data_add_node(data_queue, "members");
09763          if (!data_members) {
09764             ao2_ref(member, -1);
09765             continue;
09766          }
09767       }
09768 
09769       data_member = ast_data_add_node(data_members, "member");
09770       if (!data_member) {
09771          ao2_ref(member, -1);
09772          continue;
09773       }
09774 
09775       ast_data_add_structure(member, data_member, member);
09776 
09777       ao2_ref(member, -1);
09778    }
09779    ao2_iterator_destroy(&im);
09780 
09781    /* include the callers inside the result. */
09782    if (queue->head) {
09783       for (qe = queue->head; qe; qe = qe->next) {
09784          if (!data_callers) {
09785             data_callers = ast_data_add_node(data_queue, "callers");
09786             if (!data_callers) {
09787                continue;
09788             }
09789          }
09790 
09791          data_caller = ast_data_add_node(data_callers, "caller");
09792          if (!data_caller) {
09793             continue;
09794          }
09795 
09796          ast_data_add_structure(queue_ent, data_caller, qe);
09797 
09798          /* add the caller channel. */
09799          data_caller_channel = ast_data_add_node(data_caller, "channel");
09800          if (!data_caller_channel) {
09801             continue;
09802          }
09803 
09804          ast_channel_data_add_structure(data_caller_channel, qe->chan, 1);
09805       }
09806    }
09807 
09808    /* if this queue doesn't match remove the added queue. */
09809    if (!ast_data_search_match(search, data_queue)) {
09810       ast_data_remove_node(data_root, data_queue);
09811    }
09812 }
09813 
09814 /*!
09815  * \internal
09816  * \brief Callback used to generate the queues tree.
09817  * \param[in] search The search pattern tree.
09818  * \retval NULL on error.
09819  * \retval non-NULL The generated tree.
09820  */
09821 static int queues_data_provider_get(const struct ast_data_search *search,
09822    struct ast_data *data_root)
09823 {
09824    struct ao2_iterator i;
09825    struct call_queue *queue, *queue_realtime = NULL;
09826    struct ast_config *cfg;
09827    char *queuename;
09828 
09829    /* load realtime queues. */
09830    cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
09831    if (cfg) {
09832       for (queuename = ast_category_browse(cfg, NULL);
09833             !ast_strlen_zero(queuename);
09834             queuename = ast_category_browse(cfg, queuename)) {
09835          if ((queue = find_load_queue_rt_friendly(queuename))) {
09836             queue_unref(queue);
09837          }
09838       }
09839       ast_config_destroy(cfg);
09840    }
09841 
09842    /* static queues. */
09843    i = ao2_iterator_init(queues, 0);
09844    while ((queue = ao2_iterator_next(&i))) {
09845       ao2_lock(queue);
09846       if (queue->realtime) {
09847          queue_realtime = find_load_queue_rt_friendly(queue->name);
09848          if (!queue_realtime) {
09849             ao2_unlock(queue);
09850             queue_unref(queue);
09851             continue;
09852          }
09853          queue_unref(queue_realtime);
09854       }
09855 
09856       queues_data_provider_get_helper(search, data_root, queue);
09857       ao2_unlock(queue);
09858       queue_unref(queue);
09859    }
09860    ao2_iterator_destroy(&i);
09861 
09862    return 0;
09863 }
09864 
09865 static const struct ast_data_handler queues_data_provider = {
09866    .version = AST_DATA_HANDLER_VERSION,
09867    .get = queues_data_provider_get
09868 };
09869 
09870 static const struct ast_data_entry queue_data_providers[] = {
09871    AST_DATA_ENTRY("asterisk/application/queue/list", &queues_data_provider),
09872 };
09873 
09874 static int unload_module(void)
09875 {
09876    int res;
09877    struct ao2_iterator q_iter;
09878    struct call_queue *q = NULL;
09879 
09880    ast_cli_unregister_multiple(cli_queue, ARRAY_LEN(cli_queue));
09881    res = ast_manager_unregister("QueueStatus");
09882    res |= ast_manager_unregister("Queues");
09883    res |= ast_manager_unregister("QueueRule");
09884    res |= ast_manager_unregister("QueueSummary");
09885    res |= ast_manager_unregister("QueueAdd");
09886    res |= ast_manager_unregister("QueueRemove");
09887    res |= ast_manager_unregister("QueuePause");
09888    res |= ast_manager_unregister("QueueLog");
09889    res |= ast_manager_unregister("QueuePenalty");
09890    res |= ast_manager_unregister("QueueReload");
09891    res |= ast_manager_unregister("QueueReset");
09892    res |= ast_manager_unregister("QueueMemberRingInUse");
09893    res |= ast_unregister_application(app_aqm);
09894    res |= ast_unregister_application(app_rqm);
09895    res |= ast_unregister_application(app_pqm);
09896    res |= ast_unregister_application(app_upqm);
09897    res |= ast_unregister_application(app_ql);
09898    res |= ast_unregister_application(app);
09899    res |= ast_custom_function_unregister(&queueexists_function);
09900    res |= ast_custom_function_unregister(&queuevar_function);
09901    res |= ast_custom_function_unregister(&queuemembercount_function);
09902    res |= ast_custom_function_unregister(&queuemembercount_dep);
09903    res |= ast_custom_function_unregister(&queuememberlist_function);
09904    res |= ast_custom_function_unregister(&queuewaitingcount_function);
09905    res |= ast_custom_function_unregister(&queuememberpenalty_function);
09906 
09907    res |= ast_data_unregister(NULL);
09908 
09909    if (device_state_sub)
09910       ast_event_unsubscribe(device_state_sub);
09911 
09912    ast_extension_state_del(0, extension_state_cb);
09913 
09914    q_iter = ao2_iterator_init(queues, 0);
09915    while ((q = ao2_t_iterator_next(&q_iter, "Iterate through queues"))) {
09916       queues_t_unlink(queues, q, "Remove queue from container due to unload");
09917       queue_t_unref(q, "Done with iterator");
09918    }
09919    ao2_iterator_destroy(&q_iter);
09920    devicestate_tps = ast_taskprocessor_unreference(devicestate_tps);
09921    ao2_ref(queues, -1);
09922    ast_unload_realtime("queue_members");
09923    return res;
09924 }
09925 
09926 static int load_module(void)
09927 {
09928    int res;
09929    struct ast_flags mask = {AST_FLAGS_ALL, };
09930    struct ast_config *member_config;
09931 
09932    queues = ao2_container_alloc(MAX_QUEUE_BUCKETS, queue_hash_cb, queue_cmp_cb);
09933 
09934    use_weight = 0;
09935 
09936    if (reload_handler(0, &mask, NULL))
09937       return AST_MODULE_LOAD_DECLINE;
09938 
09939    ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, SENTINEL);
09940 
09941    /*
09942     * This section is used to determine which name for 'ringinuse' to use in realtime members
09943     * Necessary for supporting older setups.
09944     */
09945    member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name LIKE", "%", SENTINEL);
09946    if (!member_config) {
09947       realtime_ringinuse_field = "ringinuse";
09948    } else {
09949       const char *config_val;
09950       if ((config_val = ast_variable_retrieve(member_config, NULL, "ringinuse"))) {
09951          ast_log(LOG_NOTICE, "ringinuse field entries found in queue_members table. Using 'ringinuse'\n");
09952          realtime_ringinuse_field = "ringinuse";
09953       } else if ((config_val = ast_variable_retrieve(member_config, NULL, "ignorebusy"))) {
09954          ast_log(LOG_NOTICE, "ignorebusy field found in queue_members table with no ringinuse field. Using 'ignorebusy'\n");
09955          realtime_ringinuse_field = "ignorebusy";
09956       } else {
09957          ast_log(LOG_NOTICE, "No entries were found for ringinuse/ignorebusy in queue_members table. Using 'ringinuse'\n");
09958          realtime_ringinuse_field = "ringinuse";
09959       }
09960    }
09961 
09962    ast_config_destroy(member_config);
09963 
09964    if (queue_persistent_members)
09965       reload_queue_members();
09966 
09967    ast_data_register_multiple(queue_data_providers, ARRAY_LEN(queue_data_providers));
09968 
09969    ast_cli_register_multiple(cli_queue, ARRAY_LEN(cli_queue));
09970    res = ast_register_application_xml(app, queue_exec);
09971    res |= ast_register_application_xml(app_aqm, aqm_exec);
09972    res |= ast_register_application_xml(app_rqm, rqm_exec);
09973    res |= ast_register_application_xml(app_pqm, pqm_exec);
09974    res |= ast_register_application_xml(app_upqm, upqm_exec);
09975    res |= ast_register_application_xml(app_ql, ql_exec);
09976    res |= ast_manager_register_xml("Queues", 0, manager_queues_show);
09977    res |= ast_manager_register_xml("QueueStatus", 0, manager_queues_status);
09978    res |= ast_manager_register_xml("QueueSummary", 0, manager_queues_summary);
09979    res |= ast_manager_register_xml("QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member);
09980    res |= ast_manager_register_xml("QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member);
09981    res |= ast_manager_register_xml("QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member);
09982    res |= ast_manager_register_xml("QueueLog", EVENT_FLAG_AGENT, manager_queue_log_custom);
09983    res |= ast_manager_register_xml("QueuePenalty", EVENT_FLAG_AGENT, manager_queue_member_penalty);
09984    res |= ast_manager_register_xml("QueueMemberRingInUse", EVENT_FLAG_AGENT, manager_queue_member_ringinuse);
09985    res |= ast_manager_register_xml("QueueRule", 0, manager_queue_rule_show);
09986    res |= ast_manager_register_xml("QueueReload", 0, manager_queue_reload);
09987    res |= ast_manager_register_xml("QueueReset", 0, manager_queue_reset);
09988    res |= ast_custom_function_register(&queuevar_function);
09989    res |= ast_custom_function_register(&queueexists_function);
09990    res |= ast_custom_function_register(&queuemembercount_function);
09991    res |= ast_custom_function_register(&queuemembercount_dep);
09992    res |= ast_custom_function_register(&queuememberlist_function);
09993    res |= ast_custom_function_register(&queuewaitingcount_function);
09994    res |= ast_custom_function_register(&queuememberpenalty_function);
09995 
09996    if (!(devicestate_tps = ast_taskprocessor_get("app_queue", 0))) {
09997       ast_log(LOG_WARNING, "devicestate taskprocessor reference failed - devicestate notifications will not occur\n");
09998    }
09999 
10000    /* in the following subscribe call, do I use DEVICE_STATE, or DEVICE_STATE_CHANGE? */
10001    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "AppQueue Device state", NULL, AST_EVENT_IE_END))) {
10002       res = -1;
10003    }
10004 
10005    ast_extension_state_add(NULL, NULL, extension_state_cb, NULL);
10006 
10007    return res ? AST_MODULE_LOAD_DECLINE : 0;
10008 }
10009 
10010 static int reload(void)
10011 {
10012    struct ast_flags mask = {AST_FLAGS_ALL & ~QUEUE_RESET_STATS,};
10013    ast_unload_realtime("queue_members");
10014    reload_handler(1, &mask, NULL);
10015    return 0;
10016 }
10017 
10018 /* \brief Find a member by looking up queuename and interface.
10019  * \return Returns a member or NULL if member not found.
10020 */
10021 static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface)
10022 {
10023    struct member *mem = NULL;
10024    struct call_queue *q;
10025 
10026    if ((q = find_load_queue_rt_friendly(queuename))) {
10027       ao2_lock(q);
10028       mem = ao2_find(q->members, interface, OBJ_KEY);
10029       ao2_unlock(q);
10030       queue_t_unref(q, "Expiring temporary reference.");
10031    }
10032    return mem;
10033 }
10034 
10035 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "True Call Queueing",
10036       .load = load_module,
10037       .unload = unload_module,
10038       .reload = reload,
10039       .load_pri = AST_MODPRI_DEVSTATE_CONSUMER,
10040       .nonoptreq = "res_monitor",
10041           );
10042