Thu Oct 11 06:33:33 2012

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