BuildSystem: Remove unused variables.
[asterisk/asterisk.git] / main / features_config.c
1 /*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Mark Michelson <mmichelson@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19 #include "asterisk.h"
20
21 #include "asterisk/features_config.h"
22 #include "asterisk/config_options.h"
23 #include "asterisk/datastore.h"
24 #include "asterisk/channel.h"
25 #include "asterisk/pbx.h"
26 #include "asterisk/app.h"
27 #include "asterisk/cli.h"
28
29 /*** DOCUMENTATION
30         <configInfo name="features" language="en_US">
31                 <synopsis>Features Configuration</synopsis>
32                 <configFile name="features.conf">
33                         <configObject name="globals">
34                                 <synopsis>
35                                 </synopsis>
36                                 <configOption name="featuredigittimeout" default="1000">
37                                         <synopsis>Milliseconds allowed between digit presses when entering a feature code.</synopsis>
38                                 </configOption>
39                                 <configOption name="courtesytone">
40                                         <synopsis>Sound to play when automon or automixmon is activated</synopsis>
41                                 </configOption>
42                                 <configOption name="recordingfailsound">
43                                         <synopsis>Sound to play when automon or automixmon is attempted but fails to start</synopsis>
44                                 </configOption>
45                                 <configOption name="transferdigittimeout" default="3">
46                                         <synopsis>Seconds allowed between digit presses when dialing a transfer destination</synopsis>
47                                 </configOption>
48                                 <configOption name="atxfernoanswertimeout" default="15">
49                                         <synopsis>Seconds to wait for attended transfer destination to answer</synopsis>
50                                 </configOption>
51                                 <configOption name="atxferdropcall" default="no">
52                                         <synopsis>Hang up the call entirely if the attended transfer fails</synopsis>
53                                         <description>
54                                                 <para>When this option is set to <literal>no</literal>, then Asterisk will attempt to
55                                                 re-call the transferrer if the call to the transfer target fails. If the call to the
56                                                 transferrer fails, then Asterisk will wait <replaceable>atxferloopdelay</replaceable>
57                                                 milliseconds and then attempt to dial the transfer target again. This process will
58                                                 repeat until <replaceable>atxfercallbackretries</replaceable> attempts to re-call
59                                                 the transferrer have occurred.</para>
60                                                 <para>When this option is set to <literal>yes</literal>, then Asterisk will not attempt
61                                                 to re-call the transferrer if the call to the transfer target fails. Asterisk will instead
62                                                 hang up all channels involved in the transfer.</para>
63                                         </description>
64                                 </configOption>
65                                 <configOption name="atxferloopdelay" default="10">
66                                         <synopsis>Seconds to wait between attempts to re-dial transfer destination</synopsis>
67                                         <see-also><ref type="configOption">atxferdropcall</ref></see-also>
68                                 </configOption>
69                                 <configOption name="atxfercallbackretries" default="2">
70                                         <synopsis>Number of times to re-attempt dialing a transfer destination</synopsis>
71                                         <see-also><ref type="configOption">atxferdropcall</ref></see-also>
72                                 </configOption>
73                                 <configOption name="xfersound" default="beep">
74                                         <synopsis>Sound to play to during transfer and transfer-like operations.</synopsis>
75                                         <description>
76                                                 <para>This sound will play to the transferrer and transfer target channels when
77                                                 an attended transfer completes. This sound is also played to channels when performing
78                                                 an AMI <literal>Bridge</literal> action.</para>
79                                         </description>
80                                 </configOption>
81                                 <configOption name="xferfailsound" default="beeperr">
82                                         <synopsis>Sound to play to a transferee when a transfer fails</synopsis>
83                                 </configOption>
84                                 <configOption name="atxferabort" default="*1">
85                                         <synopsis>Digits to dial to abort an attended transfer attempt</synopsis>
86                                         <description>
87                                                 <para>This option is only available to the transferrer during an attended
88                                                 transfer operation. Aborting a transfer results in the transfer being cancelled and
89                                                 the original parties in the call being re-bridged.</para>
90                                         </description>
91                                 </configOption>
92                                 <configOption name="atxfercomplete" default="*2">
93                                         <synopsis>Digits to dial to complete an attended transfer</synopsis>
94                                         <description>
95                                                 <para>This option is only available to the transferrer during an attended
96                                                 transfer operation. Completing the transfer with a DTMF sequence is functionally
97                                                 equivalent to hanging up the transferrer channel during an attended transfer. The
98                                                 result is that the transfer target and transferees are bridged.</para>
99                                         </description>
100                                 </configOption>
101                                 <configOption name="atxferthreeway" default="*3">
102                                         <synopsis>Digits to dial to change an attended transfer into a three-way call</synopsis>
103                                         <description>
104                                                 <para>This option is only available to the transferrer during an attended
105                                                 transfer operation. Pressing this DTMF sequence will result in the transferrer,
106                                                 the transferees, and the transfer target all being in a single bridge together.</para>
107                                         </description>
108                                 </configOption>
109                                 <configOption name="atxferswap" default="*4">
110                                         <synopsis>Digits to dial to toggle who the transferrer is currently bridged to during an attended transfer</synopsis>
111                                         <description>
112                                                 <para>This option is only available to the transferrer during an attended
113                                                 transfer operation. Pressing this DTMF sequence will result in the transferrer swapping
114                                                 which party he is bridged with. For instance, if the transferrer is currently bridged with
115                                                 the transfer target, then pressing this DTMF sequence will cause the transferrer to be
116                                                 bridged with the transferees.</para>
117                                         </description>
118                                 </configOption>
119                                 <configOption name="pickupexten" default="*8">
120                                         <synopsis>Digits used for picking up ringing calls</synopsis>
121                                         <description>
122                                                 <para>In order for the pickup attempt to be successful, the party attempting to
123                                                 pick up the call must either have a <replaceable>namedpickupgroup</replaceable> in
124                                                 common with a ringing party's <replaceable>namedcallgroup</replaceable> or must
125                                                 have a <replaceable>pickupgroup</replaceable> in common with a ringing party's
126                                                 <replaceable>callgroup</replaceable>.</para>
127                                         </description>
128                                 </configOption>
129                                 <configOption name="pickupsound">
130                                         <synopsis>Sound to play to picker when a call is picked up</synopsis>
131                                 </configOption>
132                                 <configOption name="pickupfailsound">
133                                         <synopsis>Sound to play to picker when a call cannot be picked up</synopsis>
134                                 </configOption>
135                                 <configOption name="transferdialattempts" default="3">
136                                         <synopsis>Number of dial attempts allowed when attempting a transfer</synopsis>
137                                 </configOption>
138                                 <configOption name="transferretrysound" default="pbx-invalid">
139                                         <synopsis>Sound that is played when an incorrect extension is dialed and the transferer should try again.</synopsis>
140                                 </configOption>
141                                 <configOption name="transferinvalidsound" default="privacy-incorrect">
142                                         <synopsis>Sound that is played when an incorrect extension is dialed and the transferer has no attempts remaining.</synopsis>
143                                 </configOption>
144                         </configObject>
145                         <configObject name="featuremap">
146                                 <synopsis>DTMF options that can be triggered during bridged calls</synopsis>
147                                 <configOption name="atxfer">
148                                         <synopsis>DTMF sequence to initiate an attended transfer</synopsis>
149                                         <description>
150                                                 <para>The transferee parties will be placed on hold and the
151                                                 transferrer may dial an extension to reach a transfer target. During an
152                                                 attended transfer, the transferrer may consult with the transfer target
153                                                 before completing the transfer. Once the transferrer has hung up or pressed
154                                                 the <replaceable>atxfercomplete</replaceable> DTMF sequence, then the transferees
155                                                 and transfer target will be bridged.</para>
156                                         </description>
157                                 </configOption>
158                                 <configOption name="blindxfer" default="#">
159                                         <synopsis>DTMF sequence to initiate a blind transfer</synopsis>
160                                         <description>
161                                                 <para>The transferee parties will be placed on hold and the
162                                                 transferrer may dial an extension to reach a transfer target. During a
163                                                 blind transfer, as soon as the transfer target is dialed, the transferrer
164                                                 is hung up.</para>
165                                         </description>
166                                 </configOption>
167                                 <configOption name="disconnect" default="*">
168                                         <synopsis>DTMF sequence to disconnect the current call</synopsis>
169                                         <description>
170                                                 <para>Entering this DTMF sequence will cause the bridge to end, no
171                                                 matter the number of parties present</para>
172                                         </description>
173                                 </configOption>
174                                 <configOption name="parkcall">
175                                         <synopsis>DTMF sequence to park a call</synopsis>
176                                         <description>
177                                                 <para>The parking lot used to park the call is determined by using either the
178                                                 <replaceable>PARKINGLOT</replaceable> channel variable or a configured value on
179                                                 the channel (provided by the channel driver) if the variable is not present. If
180                                                 no configured value on the channel is present, then <literal>"default"</literal>
181                                                 is used. The call is parked in the next available space in the parking lot.</para>
182                                         </description>
183                                 </configOption>
184                                 <configOption name="automon">
185                                         <synopsis>DTMF sequence to start or stop monitoring a call</synopsis>
186                                         <description>
187                                                 <para>This will cause the channel that pressed the DTMF sequence
188                                                 to be monitored by the <literal>Monitor</literal> application. The
189                                                 format for the recording is determined by the <replaceable>TOUCH_MONITOR_FORMAT</replaceable>
190                                                 channel variable. If this variable is not specified, then <literal>wav</literal> is the
191                                                 default. The filename is constructed in the following manner:</para>
192
193                                                 <para>    prefix-timestamp-filename</para>
194
195                                                 <para>where prefix is either the value of the <replaceable>TOUCH_MONITOR_PREFIX</replaceable>
196                                                 channel variable or <literal>auto</literal> if the variable is not set. The timestamp
197                                                 is a UNIX timestamp. The filename is either the value of the <replaceable>TOUCH_MONITOR</replaceable>
198                                                 channel variable or the callerID of the channels if the variable is not set.</para>
199                                         </description>
200                                 </configOption>
201                                 <configOption name="automixmon">
202                                         <synopsis>DTMF sequence to start or stop mixmonitoring a call </synopsis>
203                                         <description>
204                                                 <para>Operation of the automixmon is similar to the <literal> automon </literal>
205                                                 feature, with the following exceptions:
206                                                         <replaceable>TOUCH_MIXMONITOR</replaceable> is used in place of <replaceable>TOUCH_MONITOR</replaceable>
207                                                         <replaceable>TOUCH_MIXMONITOR_FORMAT</replaceable> is used in place of <replaceable>TOUCH_MIXMONITOR</replaceable>
208                                                         There is no equivalent for <replaceable>TOUCH_MONITOR_PREFIX</replaceable>. <literal>"auto"</literal> is always how the filename begins.</para>
209                                         </description>
210                                         <see-also><ref type="configOption">automon</ref></see-also>
211                                 </configOption>
212                         </configObject>
213                         <configObject name="applicationmap">
214                                 <synopsis>Section for defining custom feature invocations during a call</synopsis>
215                                 <description>
216                                         <para>The applicationmap is an area where new custom features can be created. Items
217                                         defined in the applicationmap are not automatically accessible to bridged parties. Access
218                                         to the individual items is controled using the <replaceable>DYNAMIC_FEATURES</replaceable> channel variable.
219                                         The <replaceable>DYNAMIC_FEATURES</replaceable> is a <literal>#</literal> separated list of
220                                         either applicationmap item names or featuregroup names.</para>
221                                 </description>
222                                 <configOption name="">
223                                         <synopsis>A custom feature to invoke during a bridged call</synopsis>
224                                         <description>
225                                                 <para>Each item listed here is a comma-separated list of parameters that determine
226                                                 how a feature may be invoked during a call</para>
227                                                 <para>    Example:</para>
228                                                 <para>    eggs = *5,self,Playback(hello-world),default</para>
229                                                 <para>This would create a feature called <literal>eggs</literal> that could be invoked
230                                                 during a call by pressing the <literal>*5</literal>. The party that presses the DTMF
231                                                 sequence would then trigger the <literal>Playback</literal> application to play the
232                                                 <literal>hello-world</literal> file. The application invocation would happen on the
233                                                 party that pressed the DTMF sequence since <literal>self</literal> is specified. The
234                                                 other parties in the bridge would hear the <literal>default</literal> music on hold
235                                                 class during the playback.</para>
236                                                 <para>In addition to the syntax outlined in this documentation, a backwards-compatible alternative
237                                                 is also allowed. The following applicationmap lines are functionally identical:</para>
238                                                 <para>    eggs = *5,self,Playback(hello-world),default</para>
239                                                 <para>    eggs = *5,self,Playback,hello-world,default</para>
240                                                 <para>    eggs = *5,self,Playback,"hello-world",default</para>
241                                         </description>
242                                         <syntax argsep=",">
243                                                 <parameter name="dtmf" required="true">
244                                                         <para>The DTMF sequence used to trigger the option</para>
245                                                 </parameter>
246                                                 <parameter name="activate_on" required="true">
247                                                         <para>The party that the feature will be invoked on</para>
248                                                         <optionlist>
249                                                                 <option name="self"><para>Feature is invoked on party that presses the DTMF sequence</para></option>
250                                                                 <option name="peer"><para>Feature is invoked on other parties in the bridge</para></option>
251                                                         </optionlist>
252                                                 </parameter>
253                                                 <parameter name="app" required="true">
254                                                         <para>The dialplan application to run when the DTMF sequence is pressed</para>
255                                                         <argument name="app_args" required="false">
256                                                                 <para>The arguments to the dialplan application to run</para>
257                                                         </argument>
258                                                 </parameter>
259                                                 <parameter name="moh_class" required="false">
260                                                         <para>Music on hold class to play to bridge participants that are not the target of the application invocation</para>
261                                                 </parameter>
262                                         </syntax>
263                                 </configOption>
264                         </configObject>
265                         <configObject name="featuregroup">
266                                 <synopsis>Groupings of items from the applicationmap</synopsis>
267                                 <description>
268                                         <para>Feature groups allow for multiple applicationmap items to be
269                                         grouped together. Like with individual applicationmap items, feature groups
270                                         can be part of the <replaceable>DYNAMIC_FEATURES</replaceable> channel variable.
271                                         In addition to creating groupings, the feature group section allows for the
272                                         DTMF sequence used to invoke an applicationmap item to be overridden with
273                                         a different sequence.</para>
274                                 </description>
275                                 <configOption name="">
276                                         <synopsis>Applicationmap item to place in the feature group</synopsis>
277                                         <description>
278                                                 <para>Each item here must be a name of an item in the applicationmap. The
279                                                 argument may either be a new DTMF sequence to use for the item or it
280                                                 may be left blank in order to use the DTMF sequence specified in the
281                                                 applicationmap. For example:</para>
282                                                 <para>  eggs => *1</para>
283                                                 <para>  bacon =></para>
284                                                 <para>would result in the applicationmap items <literal>eggs</literal> and
285                                                 <literal>bacon</literal> being in the featuregroup. The former would have its
286                                                 default DTMF trigger overridden with <literal>*1</literal> and the latter would
287                                                 have the DTMF value specified in the applicationmap.</para>
288                                         </description>
289                                 </configOption>
290                         </configObject>
291                 </configFile>
292         </configInfo>
293         <function name="FEATURE" language="en_US">
294                 <synopsis>
295                         Get or set a feature option on a channel.
296                 </synopsis>
297                 <syntax>
298                         <parameter name="option_name" required="true">
299                                 <para>The allowed values are:</para>
300                                 <enumlist>
301                                         <enum name="inherit"><para>Inherit feature settings made in FEATURE or FEATUREMAP to child channels.</para></enum>
302                                         <enum name="featuredigittimeout"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='featuredigittimeout']/synopsis/text())" /></para></enum>
303                                         <enum name="transferdigittimeout"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='transferdigittimeout']/synopsis/text())" /></para></enum>
304                                         <enum name="atxfernoanswertimeout"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxfernoanswertimeout']/synopsis/text())" /></para></enum>
305                                         <enum name="atxferdropcall"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxferdropcall']/synopsis/text())" /></para></enum>
306                                         <enum name="atxferloopdelay"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxferloopdelay']/synopsis/text())" /></para></enum>
307                                         <enum name="atxfercallbackretries"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxfercallbackretries']/synopsis/text())" /></para></enum>
308                                         <enum name="xfersound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='xfersound']/synopsis/text())" /></para></enum>
309                                         <enum name="xferfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='xferfailsound']/synopsis/text())" /></para></enum>
310                                         <enum name="atxferabort"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxferabort']/synopsis/text())" /></para></enum>
311                                         <enum name="atxfercomplete"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxfercomplete']/synopsis/text())" /></para></enum>
312                                         <enum name="atxferthreeway"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxferthreeway']/synopsis/text())" /></para></enum>
313                                         <enum name="pickupexten"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='pickupexten']/synopsis/text())" /></para></enum>
314                                         <enum name="pickupsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='pickupsound']/synopsis/text())" /></para></enum>
315                                         <enum name="pickupfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='pickupfailsound']/synopsis/text())" /></para></enum>
316                                         <enum name="courtesytone"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='courtesytone']/synopsis/text())" /></para></enum>
317                                         <enum name="recordingfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='recordingfailsound']/synopsis/text())" /></para></enum>
318                                         <enum name="transferdialattempts"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='transferdialattempts']/synopsis/text())" /></para></enum>
319                                         <enum name="transferretrysound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='transferretrysound']/synopsis/text())" /></para></enum>
320                                         <enum name="transferinvalidsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='transferinvalidsound']/synopsis/text())" /></para></enum>
321                                 </enumlist>
322                         </parameter>
323                 </syntax>
324                 <description>
325                         <para>When this function is used as a read, it will get the current
326                         value of the specified feature option for this channel.  It will be
327                         the value of this option configured in features.conf if a channel specific
328                         value has not been set.  This function can also be used to set a channel
329                         specific value for the supported feature options.</para>
330                 </description>
331                 <see-also>
332                         <ref type="function">FEATUREMAP</ref>
333                 </see-also>
334         </function>
335         <function name="FEATUREMAP" language="en_US">
336                 <synopsis>
337                         Get or set a feature map to a given value on a specific channel.
338                 </synopsis>
339                 <syntax>
340                         <parameter name="feature_name" required="true">
341                                 <para>The allowed values are:</para>
342                                 <enumlist>
343                                         <enum name="atxfer"><para>Attended Transfer</para></enum>
344                                         <enum name="blindxfer"><para>Blind Transfer</para></enum>
345                                         <enum name="automon"><para>Auto Monitor</para></enum>
346                                         <enum name="disconnect"><para>Call Disconnect</para></enum>
347                                         <enum name="parkcall"><para>Park Call</para></enum>
348                                         <enum name="automixmon"><para>Auto MixMonitor</para></enum>
349                                 </enumlist>
350                         </parameter>
351                 </syntax>
352                 <description>
353                         <para>When this function is used as a read, it will get the current
354                         digit sequence mapped to the specified feature for this channel.  This
355                         value will be the one configured in features.conf if a channel specific
356                         value has not been set.  This function can also be used to set a channel
357                         specific value for a feature mapping.</para>
358                 </description>
359                 <see-also>
360                         <ref type="function">FEATURE</ref>
361                 </see-also>
362         </function>
363  ***/
364 /*! Default general options */
365 #define DEFAULT_FEATURE_DIGIT_TIMEOUT               1000
366 #define DEFAULT_COURTESY_TONE                       ""
367 #define DEFAULT_RECORDING_FAIL_SOUND                ""
368
369 /*! Default xfer options */
370 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT              3
371 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER  15
372 #define DEFAULT_ATXFER_DROP_CALL                    0
373 #define DEFAULT_ATXFER_LOOP_DELAY                   10
374 #define DEFAULT_ATXFER_CALLBACK_RETRIES             2
375 #define DEFAULT_XFERSOUND                           "beep"
376 #define DEFAULT_XFERFAILSOUND                       "beeperr"
377 #define DEFAULT_ATXFER_ABORT                        "*1"
378 #define DEFAULT_ATXFER_COMPLETE                     "*2"
379 #define DEFAULT_ATXFER_THREEWAY                     "*3"
380 #define DEFAULT_ATXFER_SWAP                         "*4"
381 #define DEFAULT_TRANSFER_DIAL_ATTEMPTS              3
382 #define DEFAULT_TRANSFER_RETRY_SOUND                "pbx-invalid"
383 #define DEFAULT_TRANSFER_INVALID_SOUND              "privacy-incorrect"
384
385 /*! Default pickup options */
386 #define DEFAULT_PICKUPEXTEN                         "*8"
387 #define DEFAULT_PICKUPSOUND                         ""
388 #define DEFAULT_PICKUPFAILSOUND                     ""
389
390 /*! Default featuremap options */
391 #define DEFAULT_FEATUREMAP_BLINDXFER                "#"
392 #define DEFAULT_FEATUREMAP_DISCONNECT               "*"
393 #define DEFAULT_FEATUREMAP_AUTOMON                  ""
394 #define DEFAULT_FEATUREMAP_ATXFER                   ""
395 #define DEFAULT_FEATUREMAP_PARKCALL                 ""
396 #define DEFAULT_FEATUREMAP_AUTOMIXMON               ""
397
398 /*!
399  * \brief Configuration from the "general" section of features.conf
400  */
401 struct features_global_config {
402         struct ast_features_general_config *general;
403         struct ast_features_xfer_config *xfer;
404         struct ast_features_pickup_config *pickup;
405 };
406
407 static void ast_applicationmap_item_destructor(void *obj)
408 {
409         struct ast_applicationmap_item *item = obj;
410
411         ast_string_field_free_memory(item);
412 }
413
414 static int applicationmap_sort(const void *obj, const void *arg, int flags)
415 {
416         const struct ast_applicationmap_item *item1 = obj;
417         const struct ast_applicationmap_item *item2;
418         const char *key2;
419
420         switch(flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
421         case OBJ_KEY:
422                 key2 = arg;
423                 return strcasecmp(item1->name, key2);
424         case OBJ_PARTIAL_KEY:
425                 key2 = arg;
426                 return strncasecmp(item1->name, key2, strlen(key2));
427         default:
428         case OBJ_POINTER:
429                 item2 = arg;
430                 return strcasecmp(item1->name, item2->name);
431         }
432 }
433
434 /*!
435  * \brief Entry in the container of featuregroups
436  */
437 struct featuregroup_item {
438         AST_DECLARE_STRING_FIELDS(
439                 /*! The name of the applicationmap item that we are referring to */
440                 AST_STRING_FIELD(appmap_item_name);
441                 /*! Custom DTMF override to use instead of the default for the applicationmap item */
442                 AST_STRING_FIELD(dtmf_override);
443         );
444         /*! The applicationmap item that is being referred to */
445         struct ast_applicationmap_item *appmap_item;
446 };
447
448 static void featuregroup_item_destructor(void *obj)
449 {
450         struct featuregroup_item *item = obj;
451
452         ast_string_field_free_memory(item);
453         ao2_cleanup(item->appmap_item);
454 }
455
456 static int group_item_sort(const void *obj, const void *arg, int flags)
457 {
458         const struct featuregroup_item *item1 = obj;
459         const struct featuregroup_item *item2;
460         const char *key2;
461
462         switch(flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
463         case OBJ_KEY:
464                 key2 = arg;
465                 return strcasecmp(item1->appmap_item_name, key2);
466         case OBJ_PARTIAL_KEY:
467                 key2 = arg;
468                 return strncasecmp(item1->appmap_item_name, key2, strlen(key2));
469         case OBJ_POINTER:
470                 item2 = arg;
471                 return strcasecmp(item1->appmap_item_name, item2->appmap_item_name);
472         default:
473                 return CMP_STOP;
474         }
475 }
476
477 /*!
478  * \brief Featuregroup representation
479  */
480 struct featuregroup {
481         /*! The name of the featuregroup */
482         const char *name;
483         /*! A container of featuregroup_items */
484         struct ao2_container *items;
485 };
486
487 static int featuregroup_hash(const void *obj, int flags)
488 {
489         const struct featuregroup *group;
490         const char *key;
491
492         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
493         case OBJ_KEY:
494                 key = obj;
495                 return ast_str_case_hash(key);
496         case OBJ_PARTIAL_KEY:
497                 ast_assert(0);
498                 return 0;
499         case OBJ_POINTER:
500         default:
501                 group = obj;
502                 return ast_str_case_hash(group->name);
503         }
504 }
505
506 static int featuregroup_cmp(void *obj, void *arg, int flags)
507 {
508         struct featuregroup *group1 = obj;
509         struct featuregroup *group2;
510         const char *key2;
511
512         switch(flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
513         case OBJ_KEY:
514                 key2 = arg;
515                 return strcasecmp(group1->name, key2) ? 0 : CMP_MATCH;
516         case OBJ_PARTIAL_KEY:
517                 key2 = arg;
518                 return strncasecmp(group1->name, key2, strlen(key2)) ? 0 : CMP_MATCH;
519         case OBJ_POINTER:
520                 group2 = arg;
521                 return strcasecmp(group1->name, group2->name) ? 0 : CMP_MATCH;
522         default:
523                 return CMP_STOP;
524         }
525 }
526
527 static void *featuregroup_find(struct ao2_container *group_container, const char *category)
528 {
529         return ao2_find(group_container, category, OBJ_KEY);
530 }
531
532 static void featuregroup_destructor(void *obj)
533 {
534         struct featuregroup *group = obj;
535
536         ast_free((char *) group->name);
537         ao2_cleanup(group->items);
538 }
539
540 static void *featuregroup_alloc(const char *cat)
541 {
542         struct featuregroup *group;
543
544         group = ao2_alloc(sizeof(*group), featuregroup_destructor);
545         if (!group) {
546                 return NULL;
547         }
548
549         group->name = ast_strdup(cat);
550         if (!group->name) {
551                 ao2_cleanup(group);
552                 return NULL;
553         }
554
555         group->items = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
556                 AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, group_item_sort, NULL);
557         if (!group->items) {
558                 ao2_cleanup(group);
559                 return NULL;
560         }
561
562         return group;
563 }
564
565 /* Used for deprecated parking configuration */
566 struct dummy_config {
567         char dummy;
568 };
569
570 struct features_config {
571         struct features_global_config *global;
572         struct ast_featuremap_config *featuremap;
573         struct dummy_config *parkinglots;
574         struct ao2_container *applicationmap;
575         struct ao2_container *featuregroups;
576 };
577
578 static struct aco_type global_option = {
579         .type = ACO_GLOBAL,
580         .name = "globals",
581         .category_match = ACO_WHITELIST_EXACT,
582         .category = "general",
583         .item_offset = offsetof(struct features_config, global),
584 };
585
586 static struct aco_type featuremap_option = {
587         .type = ACO_GLOBAL,
588         .name = "featuremap",
589         .category_match = ACO_WHITELIST_EXACT,
590         .category = "featuremap",
591         .item_offset = offsetof(struct features_config, featuremap),
592 };
593
594 static struct aco_type applicationmap_option = {
595         .type = ACO_GLOBAL,
596         .name = "applicationmap",
597         .category_match = ACO_WHITELIST_EXACT,
598         .category = "applicationmap",
599         .item_offset = offsetof(struct features_config, applicationmap),
600 };
601
602 static struct aco_type featuregroup_option = {
603         .type = ACO_ITEM,
604         .name = "featuregroup",
605         .category_match = ACO_BLACKLIST,
606         .category = "^(general|featuremap|applicationmap|parkinglot_.*)$",
607         .item_offset = offsetof(struct features_config, featuregroups),
608         .item_alloc = featuregroup_alloc,
609         .item_find = featuregroup_find,
610 };
611
612 static struct aco_type parkinglot_option = {
613         .type = ACO_GLOBAL,
614         .name = "parkinglot",
615         .category_match = ACO_WHITELIST,
616         .category = "^parkinglot_.*$",
617         .item_offset = offsetof(struct features_config, parkinglots),
618         .hidden = 1,
619 };
620
621 static struct aco_type *global_options[] = ACO_TYPES(&global_option);
622 static struct aco_type *featuremap_options[] = ACO_TYPES(&featuremap_option);
623 static struct aco_type *applicationmap_options[] = ACO_TYPES(&applicationmap_option);
624 static struct aco_type *featuregroup_options[] = ACO_TYPES(&featuregroup_option);
625 static struct aco_type *parkinglot_options[] = ACO_TYPES(&parkinglot_option);
626
627 static struct aco_file features_conf = {
628         .filename = "features.conf",
629         .types = ACO_TYPES(&global_option, &featuremap_option, &applicationmap_option, &featuregroup_option, &parkinglot_option),
630 };
631
632 AO2_GLOBAL_OBJ_STATIC(globals);
633
634 static void features_config_destructor(void *obj)
635 {
636         struct features_config *cfg = obj;
637
638         ao2_cleanup(cfg->global);
639         ao2_cleanup(cfg->featuremap);
640         ao2_cleanup(cfg->parkinglots);
641         ao2_cleanup(cfg->applicationmap);
642         ao2_cleanup(cfg->featuregroups);
643 }
644
645 static void featuremap_config_destructor(void *obj)
646 {
647         struct ast_featuremap_config *cfg = obj;
648
649         ast_string_field_free_memory(cfg);
650 }
651
652 static void global_config_destructor(void *obj)
653 {
654         struct features_global_config *cfg = obj;
655
656         ao2_cleanup(cfg->general);
657         ao2_cleanup(cfg->xfer);
658         ao2_cleanup(cfg->pickup);
659 }
660
661 static void general_destructor(void *obj)
662 {
663         struct ast_features_general_config *cfg = obj;
664
665         ast_string_field_free_memory(cfg);
666 }
667
668 static void xfer_destructor(void *obj)
669 {
670         struct ast_features_xfer_config *cfg = obj;
671
672         ast_string_field_free_memory(cfg);
673 }
674
675 static void pickup_destructor(void *obj)
676 {
677         struct ast_features_pickup_config *cfg = obj;
678
679         ast_string_field_free_memory(cfg);
680 }
681
682 static struct features_global_config *global_config_alloc(void)
683 {
684         RAII_VAR(struct features_global_config *, cfg, NULL, ao2_cleanup);
685
686         cfg = ao2_alloc(sizeof(*cfg), global_config_destructor);
687         if (!cfg) {
688                 return NULL;
689         }
690
691         cfg->general = ao2_alloc(sizeof(*cfg->general), general_destructor);
692         if (!cfg->general || ast_string_field_init(cfg->general, 32)) {
693                 return NULL;
694         }
695
696         cfg->xfer = ao2_alloc(sizeof(*cfg->xfer), xfer_destructor);
697         if (!cfg->xfer || ast_string_field_init(cfg->xfer, 32)) {
698                 return NULL;
699         }
700
701         cfg->pickup = ao2_alloc(sizeof(*cfg->pickup), pickup_destructor);
702         if (!cfg->pickup || ast_string_field_init(cfg->pickup, 32)) {
703                 return NULL;
704         }
705
706         ao2_ref(cfg, +1);
707         return cfg;
708 }
709
710 static struct ao2_container *applicationmap_alloc(int replace_duplicates)
711 {
712         return ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
713                 replace_duplicates ? AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE : AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW,
714                 applicationmap_sort, NULL);
715 }
716
717 /*!
718  * \internal
719  * \brief Allocate the major configuration structure
720  *
721  * The parameter is used to determine if the applicationmap and featuregroup
722  * structures should be allocated. We only want to allocate these structures for
723  * the global features_config structure. For the datastores on channels, we don't
724  * need to allocate these structures because they are not used.
725  *
726  * \param allocate_applicationmap See previous explanation
727  * \retval NULL Failed to alloate configuration
728  * \retval non-NULL Allocated configuration
729  */
730 static struct features_config *__features_config_alloc(int allocate_applicationmap)
731 {
732         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
733
734         cfg = ao2_alloc(sizeof(*cfg), features_config_destructor);
735         if (!cfg) {
736                 return NULL;
737         }
738
739         cfg->global = global_config_alloc();
740         if (!cfg->global) {
741                 return NULL;
742         }
743
744         cfg->featuremap = ao2_alloc(sizeof(*cfg->featuremap), featuremap_config_destructor);
745         if (!cfg->featuremap || ast_string_field_init(cfg->featuremap, 32)) {
746                 return NULL;
747         }
748
749         cfg->parkinglots = ao2_alloc(sizeof(*cfg->parkinglots), NULL);
750         if (!cfg->parkinglots) {
751                 return NULL;
752         }
753
754         if (allocate_applicationmap) {
755                 cfg->applicationmap = applicationmap_alloc(1);
756                 if (!cfg->applicationmap) {
757                         return NULL;
758                 }
759
760                 cfg->featuregroups = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 11, featuregroup_hash,
761                         featuregroup_cmp);
762                 if (!cfg->featuregroups) {
763                         return NULL;
764                 }
765         }
766
767         ao2_ref(cfg, +1);
768         return cfg;
769
770 }
771
772 static void *features_config_alloc(void)
773 {
774         return __features_config_alloc(1);
775 }
776
777 static void general_copy(struct ast_features_general_config *dest, const struct ast_features_general_config *src)
778 {
779         ast_string_fields_copy(dest, src);
780         dest->featuredigittimeout = src->featuredigittimeout;
781 }
782
783 static void xfer_copy(struct ast_features_xfer_config *dest, const struct ast_features_xfer_config *src)
784 {
785         ast_string_fields_copy(dest, src);
786         dest->transferdigittimeout = src->transferdigittimeout;
787         dest->atxfernoanswertimeout = src->atxfernoanswertimeout;
788         dest->atxferloopdelay = src->atxferloopdelay;
789         dest->atxfercallbackretries = src->atxfercallbackretries;
790         dest->atxferdropcall = src->atxferdropcall;
791         dest->transferdialattempts = src->transferdialattempts;
792 }
793
794 static void pickup_copy(struct ast_features_pickup_config *dest, const struct ast_features_pickup_config *src)
795 {
796         ast_string_fields_copy(dest, src);
797 }
798
799 static void global_copy(struct features_global_config *dest, const struct features_global_config *src)
800 {
801         general_copy(dest->general, src->general);
802         xfer_copy(dest->xfer, src->xfer);
803         pickup_copy(dest->pickup, src->pickup);
804 }
805
806 static void featuremap_copy(struct ast_featuremap_config *dest, const struct ast_featuremap_config *src)
807 {
808         ast_string_fields_copy(dest, src);
809 }
810
811 static void features_copy(struct features_config *dest, const struct features_config *src)
812 {
813         global_copy(dest->global, src->global);
814         featuremap_copy(dest->featuremap, src->featuremap);
815
816         /* applicationmap and featuregroups are purposely not copied. A channel's applicationmap
817          * is produced on the fly when ast_get_chan_applicationmap() is called
818          * NOTE: This does not apply to the global cfg->applicationmap and cfg->featuresgroups
819          */
820 }
821
822 static struct features_config *features_config_dup(const struct features_config *orig)
823 {
824         struct features_config *dup;
825
826         dup = __features_config_alloc(0);
827         if (!dup) {
828                 return NULL;
829         }
830
831         features_copy(dup, orig);
832
833         return dup;
834 }
835
836 static int general_set(struct ast_features_general_config *general, const char *name,
837                 const char *value)
838 {
839         int res = 0;
840
841         if (!strcasecmp(name, "featuredigittimeout")) {
842                 res = ast_parse_arg(value, PARSE_INT32, &general->featuredigittimeout);
843         } else if (!strcasecmp(name, "courtesytone")) {
844                 ast_string_field_set(general, courtesytone, value);
845         } else if (!strcasecmp(name, "recordingfailsound")) {
846                 ast_string_field_set(general, recordingfailsound, value);
847         } else {
848                 /* Unrecognized option */
849                 res = -1;
850         }
851
852         return res;
853 }
854
855 static int general_get(struct ast_features_general_config *general, const char *field,
856                 char *buf, size_t len)
857 {
858         int res = 0;
859
860         if (!strcasecmp(field, "featuredigittimeout")) {
861                 snprintf(buf, len, "%u", general->featuredigittimeout);
862         } else if (!strcasecmp(field, "courtesytone")) {
863                 ast_copy_string(buf, general->courtesytone, len);
864         } else if (!strcasecmp(field, "recordingfailsound")) {
865                 ast_copy_string(buf, general->recordingfailsound, len);
866         } else {
867                 /* Unrecognized option */
868                 res = -1;
869         }
870
871         return res;
872 }
873
874 static int xfer_set(struct ast_features_xfer_config *xfer, const char *name,
875                 const char *value)
876 {
877         int res = 0;
878
879         if (!strcasecmp(name, "transferdigittimeout")) {
880                 res = ast_parse_arg(value, PARSE_INT32, &xfer->transferdigittimeout);
881         } else if (!strcasecmp(name, "atxfernoanswertimeout")) {
882                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxfernoanswertimeout);
883         } else if (!strcasecmp(name, "atxferloopdelay")) {
884                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxferloopdelay);
885         } else if (!strcasecmp(name, "atxfercallbackretries")) {
886                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxfercallbackretries);
887         } else if (!strcasecmp(name, "atxferdropcall")) {
888                 xfer->atxferdropcall = ast_true(value);
889         } else if (!strcasecmp(name, "xfersound")) {
890                 ast_string_field_set(xfer, xfersound, value);
891         } else if (!strcasecmp(name, "xferfailsound")) {
892                 ast_string_field_set(xfer, xferfailsound, value);
893         } else if (!strcasecmp(name, "atxferabort")) {
894                 ast_string_field_set(xfer, atxferabort, value);
895         } else if (!strcasecmp(name, "atxfercomplete")) {
896                 ast_string_field_set(xfer, atxfercomplete, value);
897         } else if (!strcasecmp(name, "atxferthreeway")) {
898                 ast_string_field_set(xfer, atxferthreeway, value);
899         } else if (!strcasecmp(name, "atxferswap")) {
900                 ast_string_field_set(xfer, atxferswap, value);
901         } else if (!strcasecmp(name, "transferdialattempts")) {
902                 res = ast_parse_arg(value, PARSE_INT32, &xfer->transferdialattempts);
903         } else if (!strcasecmp(name, "transferretrysound")) {
904                 ast_string_field_set(xfer, transferretrysound, value);
905         } else if (!strcasecmp(name, "transferinvalidsound")) {
906                 ast_string_field_set(xfer, transferinvalidsound, value);
907         } else {
908                 /* Unrecognized option */
909                 res = -1;
910         }
911
912         return res;
913 }
914
915 static int xfer_get(struct ast_features_xfer_config *xfer, const char *field,
916                 char *buf, size_t len)
917 {
918         int res = 0;
919
920         if (!strcasecmp(field, "transferdigittimeout")) {
921                 snprintf(buf, len, "%u", xfer->transferdigittimeout);
922         } else if (!strcasecmp(field, "atxfernoanswertimeout")) {
923                 snprintf(buf, len, "%u", xfer->atxfernoanswertimeout);
924         } else if (!strcasecmp(field, "atxferloopdelay")) {
925                 snprintf(buf, len, "%u", xfer->atxferloopdelay);
926         } else if (!strcasecmp(field, "atxfercallbackretries")) {
927                 snprintf(buf, len, "%u", xfer->atxfercallbackretries);
928         } else if (!strcasecmp(field, "atxferdropcall")) {
929                 snprintf(buf, len, "%u", xfer->atxferdropcall);
930         } else if (!strcasecmp(field, "xfersound")) {
931                 ast_copy_string(buf, xfer->xfersound, len);
932         } else if (!strcasecmp(field, "xferfailsound")) {
933                 ast_copy_string(buf, xfer->xferfailsound, len);
934         } else if (!strcasecmp(field, "atxferabort")) {
935                 ast_copy_string(buf, xfer->atxferabort, len);
936         } else if (!strcasecmp(field, "atxfercomplete")) {
937                 ast_copy_string(buf, xfer->atxfercomplete, len);
938         } else if (!strcasecmp(field, "atxferthreeway")) {
939                 ast_copy_string(buf, xfer->atxferthreeway, len);
940         } else if (!strcasecmp(field, "atxferswap")) {
941                 ast_copy_string(buf, xfer->atxferswap, len);
942         } else if (!strcasecmp(field, "transferdialattempts")) {
943                 snprintf(buf, len, "%u", xfer->transferdialattempts);
944         } else if (!strcasecmp(field, "transferretrysound")) {
945                 ast_copy_string(buf, xfer->transferretrysound, len);
946         } else if (!strcasecmp(field, "transferinvalidsound")) {
947                 ast_copy_string(buf, xfer->transferinvalidsound, len);
948         } else {
949                 /* Unrecognized option */
950                 res = -1;
951         }
952
953         return res;
954 }
955
956 static int pickup_set(struct ast_features_pickup_config *pickup, const char *name,
957                 const char *value)
958 {
959         int res = 0;
960
961         if (!strcasecmp(name, "pickupsound")) {
962                 ast_string_field_set(pickup, pickupsound, value);
963         } else if (!strcasecmp(name, "pickupfailsound")) {
964                 ast_string_field_set(pickup, pickupfailsound, value);
965         } else if (!strcasecmp(name, "pickupexten")) {
966                 ast_string_field_set(pickup, pickupexten, value);
967         } else {
968                 /* Unrecognized option */
969                 res = -1;
970         }
971
972         return res;
973 }
974
975 static int pickup_get(struct ast_features_pickup_config *pickup, const char *field,
976                 char *buf, size_t len)
977 {
978         int res = 0;
979
980         if (!strcasecmp(field, "pickupsound")) {
981                 ast_copy_string(buf, pickup->pickupsound, len);
982         } else if (!strcasecmp(field, "pickupfailsound")) {
983                 ast_copy_string(buf, pickup->pickupfailsound, len);
984         } else if (!strcasecmp(field, "pickupexten")) {
985                 ast_copy_string(buf, pickup->pickupexten, len);
986         } else {
987                 /* Unrecognized option */
988                 res = -1;
989         }
990
991         return res;
992 }
993
994 static int featuremap_set(struct ast_featuremap_config *featuremap, const char *name,
995                 const char *value)
996 {
997         int res = 0;
998
999         if (!strcasecmp(name, "blindxfer")) {
1000                 ast_string_field_set(featuremap, blindxfer, value);
1001         } else if (!strcasecmp(name, "disconnect")) {
1002                 ast_string_field_set(featuremap, disconnect, value);
1003         } else if (!strcasecmp(name, "automon")) {
1004                 ast_string_field_set(featuremap, automon, value);
1005         } else if (!strcasecmp(name, "atxfer")) {
1006                 ast_string_field_set(featuremap, atxfer, value);
1007         } else if (!strcasecmp(name, "automixmon")) {
1008                 ast_string_field_set(featuremap, automixmon, value);
1009         } else if (!strcasecmp(name, "parkcall")) {
1010                 ast_string_field_set(featuremap, parkcall, value);
1011         } else {
1012                 /* Unrecognized option */
1013                 res = -1;
1014         }
1015
1016         return res;
1017 }
1018
1019 static int featuremap_get(struct ast_featuremap_config *featuremap, const char *field,
1020                 char *buf, size_t len)
1021 {
1022         int res = 0;
1023
1024         if (!strcasecmp(field, "blindxfer")) {
1025                 ast_copy_string(buf, featuremap->blindxfer, len);
1026         } else if (!strcasecmp(field, "disconnect")) {
1027                 ast_copy_string(buf, featuremap->disconnect, len);
1028         } else if (!strcasecmp(field, "automon")) {
1029                 ast_copy_string(buf, featuremap->automon, len);
1030         } else if (!strcasecmp(field, "atxfer")) {
1031                 ast_copy_string(buf, featuremap->atxfer, len);
1032         } else if (!strcasecmp(field, "automixmon")) {
1033                 ast_copy_string(buf, featuremap->automixmon, len);
1034         } else if (!strcasecmp(field, "parkcall")) {
1035                 ast_copy_string(buf, featuremap->parkcall, len);
1036         } else {
1037                 /* Unrecognized option */
1038                 res = -1;
1039         }
1040
1041         return res;
1042 }
1043
1044 static void feature_ds_destroy(void *data)
1045 {
1046         struct features_config *cfg = data;
1047         ao2_cleanup(cfg);
1048 }
1049
1050 static void *feature_ds_duplicate(void *data)
1051 {
1052         struct features_config *old_cfg = data;
1053
1054         return features_config_dup(old_cfg);
1055 }
1056
1057 static const struct ast_datastore_info feature_ds_info = {
1058         .type = "FEATURE",
1059         .destroy = feature_ds_destroy,
1060         .duplicate = feature_ds_duplicate,
1061 };
1062
1063 /*!
1064  * \internal
1065  * \brief Find or create feature datastore on a channel
1066  *
1067  * \pre chan is locked
1068  *
1069  * \return the data on the FEATURE datastore, or NULL on error
1070  */
1071 static struct features_config *get_feature_ds(struct ast_channel *chan)
1072 {
1073         RAII_VAR(struct features_config *, orig, NULL, ao2_cleanup);
1074         struct features_config *cfg;
1075         struct ast_datastore *ds;
1076
1077         if ((ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL))) {
1078                 cfg = ds->data;
1079                 ao2_ref(cfg, +1);
1080                 return cfg;
1081         }
1082
1083         orig = ao2_global_obj_ref(globals);
1084         if (!orig) {
1085                 return NULL;
1086         }
1087
1088         cfg = features_config_dup(orig);
1089         if (!cfg) {
1090                 return NULL;
1091         }
1092
1093         if (!(ds = ast_datastore_alloc(&feature_ds_info, NULL))) {
1094                 ao2_cleanup(cfg);
1095                 return NULL;
1096         }
1097
1098         /* Give the datastore a reference to the config */
1099         ao2_ref(cfg, +1);
1100         ds->data = cfg;
1101
1102         ast_channel_datastore_add(chan, ds);
1103
1104         return cfg;
1105 }
1106
1107 static struct ast_datastore *get_feature_chan_ds(struct ast_channel *chan)
1108 {
1109         struct ast_datastore *ds;
1110
1111         if (!(ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL))) {
1112                 /* Hasn't been created yet.  Trigger creation. */
1113                 ao2_cleanup(get_feature_ds(chan));
1114
1115                 ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL);
1116         }
1117
1118         return ds;
1119 }
1120
1121 struct ast_features_general_config *ast_get_chan_features_general_config(struct ast_channel *chan)
1122 {
1123         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1124
1125         if (chan) {
1126                 cfg = get_feature_ds(chan);
1127         } else {
1128                 cfg = ao2_global_obj_ref(globals);
1129         }
1130
1131         if (!cfg) {
1132                 return NULL;
1133         }
1134
1135         ast_assert(cfg->global && cfg->global->general);
1136
1137         ao2_ref(cfg->global->general, +1);
1138         return cfg->global->general;
1139 }
1140
1141 struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_channel *chan)
1142 {
1143         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1144
1145         if (chan) {
1146                 cfg = get_feature_ds(chan);
1147         } else {
1148                 cfg = ao2_global_obj_ref(globals);
1149         }
1150
1151         if (!cfg) {
1152                 return NULL;
1153         }
1154
1155         ast_assert(cfg->global && cfg->global->xfer);
1156
1157         ao2_ref(cfg->global->xfer, +1);
1158         return cfg->global->xfer;
1159 }
1160
1161 char *ast_get_chan_features_xferfailsound(struct ast_channel *chan)
1162 {
1163         char *res;
1164         struct ast_features_xfer_config *cfg = ast_get_chan_features_xfer_config(chan);
1165
1166         if (!cfg) {
1167                 return NULL;
1168         }
1169
1170         res = ast_strdup(cfg->xferfailsound);
1171         ao2_ref(cfg, -1);
1172
1173         return res;
1174 }
1175
1176 char *ast_get_chan_features_atxferabort(struct ast_channel *chan)
1177 {
1178         char *res;
1179         struct ast_features_xfer_config *cfg = ast_get_chan_features_xfer_config(chan);
1180
1181         if (!cfg) {
1182                 return NULL;
1183         }
1184
1185         res = ast_strdup(cfg->atxferabort);
1186         ao2_ref(cfg, -1);
1187
1188         return res;
1189 }
1190
1191 struct ast_features_pickup_config *ast_get_chan_features_pickup_config(struct ast_channel *chan)
1192 {
1193         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1194
1195         if (chan) {
1196                 cfg = get_feature_ds(chan);
1197         } else {
1198                 cfg = ao2_global_obj_ref(globals);
1199         }
1200
1201         if (!cfg) {
1202                 return NULL;
1203         }
1204
1205         ast_assert(cfg->global && cfg->global->pickup);
1206
1207         ao2_ref(cfg->global->pickup, +1);
1208         return cfg->global->pickup;
1209 }
1210
1211 struct ast_featuremap_config *ast_get_chan_featuremap_config(struct ast_channel *chan)
1212 {
1213         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1214
1215         if (chan) {
1216                 cfg = get_feature_ds(chan);
1217         } else {
1218                 cfg = ao2_global_obj_ref(globals);
1219         }
1220
1221         if (!cfg) {
1222                 return NULL;
1223         }
1224
1225         ast_assert(cfg->featuremap != NULL);
1226
1227         ao2_ref(cfg->featuremap, +1);
1228         return cfg->featuremap;
1229 }
1230
1231 int ast_get_builtin_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
1232 {
1233         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1234
1235         if (chan) {
1236                 cfg = get_feature_ds(chan);
1237         } else {
1238                 cfg = ao2_global_obj_ref(globals);
1239         }
1240
1241         if (!cfg) {
1242                 return -1;
1243         }
1244
1245         return featuremap_get(cfg->featuremap, feature, buf, len);
1246 }
1247
1248 int ast_get_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
1249 {
1250         RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);
1251         RAII_VAR(struct ast_applicationmap_item *, item, NULL, ao2_cleanup);
1252
1253         if (!ast_get_builtin_feature(chan, feature, buf, len)) {
1254                 return 0;
1255         }
1256
1257         /* Dang, must be in the application map */
1258         applicationmap = ast_get_chan_applicationmap(chan);
1259         if (!applicationmap) {
1260                 return -1;
1261         }
1262
1263         item = ao2_find(applicationmap, feature, OBJ_KEY);
1264         if (!item) {
1265                 return -1;
1266         }
1267
1268         ast_copy_string(buf, item->dtmf, len);
1269         return 0;
1270 }
1271
1272 static struct ast_applicationmap_item *applicationmap_item_alloc(const char *name,
1273                 const char *app, const char *app_data, const char *moh_class, const char *dtmf,
1274                 unsigned int activate_on_self)
1275 {
1276         struct ast_applicationmap_item *item;
1277
1278         item = ao2_alloc(sizeof(*item), ast_applicationmap_item_destructor);
1279
1280         if (!item || ast_string_field_init(item, 64)) {
1281                 return NULL;
1282         }
1283
1284         ast_string_field_set(item, name, name);
1285         ast_string_field_set(item, app, app);
1286         ast_string_field_set(item, app_data, app_data);
1287         ast_string_field_set(item, moh_class, moh_class);
1288         ast_copy_string(item->dtmf, dtmf, sizeof(item->dtmf));
1289         item->activate_on_self = activate_on_self;
1290
1291         return item;
1292 }
1293
1294 static int add_item(void *obj, void *arg, int flags)
1295 {
1296         struct featuregroup_item *fg_item = obj;
1297         struct ao2_container *applicationmap = arg;
1298         RAII_VAR(struct ast_applicationmap_item *, appmap_item, NULL, ao2_cleanup);
1299
1300         /* If there's no DTMF override, then we can just link
1301          * the applicationmap item directly. Otherwise, we need
1302          * to create a copy with the DTMF override in place and
1303          * link that instead
1304          */
1305         if (ast_strlen_zero(fg_item->dtmf_override)) {
1306                 ao2_ref(fg_item->appmap_item, +1);
1307                 appmap_item = fg_item->appmap_item;
1308         } else {
1309                 appmap_item = applicationmap_item_alloc(fg_item->appmap_item_name,
1310                                 fg_item->appmap_item->app, fg_item->appmap_item->app_data,
1311                                 fg_item->appmap_item->moh_class, fg_item->dtmf_override,
1312                                 fg_item->appmap_item->activate_on_self);
1313         }
1314
1315         if (!appmap_item) {
1316                 return 0;
1317         }
1318
1319         ao2_link(applicationmap, appmap_item);
1320         return 0;
1321 }
1322
1323 struct ao2_container *ast_get_chan_applicationmap(struct ast_channel *chan)
1324 {
1325         RAII_VAR(struct features_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
1326         struct ao2_container *applicationmap;
1327         char *group_names;
1328         char *name;
1329
1330         if (!cfg) {
1331                 return NULL;
1332         }
1333
1334         if (!chan) {
1335                 if (!cfg->applicationmap || ao2_container_count(cfg->applicationmap) == 0) {
1336                         return NULL;
1337                 }
1338                 ao2_ref(cfg->applicationmap, +1);
1339                 return cfg->applicationmap;
1340         }
1341
1342         group_names = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"), ""));
1343         if (ast_strlen_zero(group_names)) {
1344                 return NULL;
1345         }
1346
1347         applicationmap = applicationmap_alloc(0);
1348         if (!applicationmap) {
1349                 return NULL;
1350         }
1351
1352         /* global config must be initialized */
1353         ast_assert(cfg->featuregroups != NULL);
1354         ast_assert(cfg->applicationmap != NULL);
1355         while ((name = strsep(&group_names, "#"))) {
1356                 RAII_VAR(struct featuregroup *, group, ao2_find(cfg->featuregroups, name, OBJ_KEY), ao2_cleanup);
1357
1358                 if (!group) {
1359                         RAII_VAR(struct ast_applicationmap_item *, item, ao2_find(cfg->applicationmap, name, OBJ_KEY), ao2_cleanup);
1360
1361                         if (item) {
1362                                 ao2_link(applicationmap, item);
1363                         } else {
1364                                 ast_log(LOG_WARNING, "Unknown DYNAMIC_FEATURES item '%s' on channel %s.\n",
1365                                         name, ast_channel_name(chan));
1366                         }
1367                 } else {
1368                         ao2_callback(group->items, 0, add_item, applicationmap);
1369                 }
1370         }
1371
1372         if (ao2_container_count(applicationmap) == 0) {
1373                 ao2_cleanup(applicationmap);
1374                 return NULL;
1375         }
1376
1377         return applicationmap;
1378 }
1379
1380 static int applicationmap_handler(const struct aco_option *opt,
1381                 struct ast_variable *var, void *obj)
1382 {
1383         RAII_VAR(struct ast_applicationmap_item *, item, NULL, ao2_cleanup);
1384         struct ao2_container *applicationmap = obj;
1385         AST_DECLARE_APP_ARGS(args,
1386                 AST_APP_ARG(dtmf);
1387                 AST_APP_ARG(activate_on);
1388                 AST_APP_ARG(app);
1389                 AST_APP_ARG(app_data);
1390                 AST_APP_ARG(moh_class);
1391         );
1392         char *parse = ast_strdupa(var->value);
1393         char *slash;
1394         char *paren;
1395         unsigned int activate_on_self;
1396
1397         AST_STANDARD_APP_ARGS(args, parse);
1398
1399         if (ast_strlen_zero(args.dtmf) ||
1400                         ast_strlen_zero(args.activate_on) ||
1401                         ast_strlen_zero(args.app)) {
1402                 ast_log(LOG_WARNING, "Invalid applicationmap syntax for '%s'. Missing required argument\n", var->name);
1403                 return -1;
1404         }
1405
1406         /* features.conf used to have an "activated_by" portion
1407          * in addition to activate_on. Get rid of whatever may be
1408          * there
1409          */
1410         slash = strchr(args.activate_on, '/');
1411         if (slash) {
1412                 *slash = '\0';
1413         }
1414
1415         /* Some applications do not require arguments. */
1416         if (!args.app_data) {
1417                 args.app_data = "";
1418         }
1419
1420         /* Two syntaxes allowed for applicationmap:
1421          * Old: foo = *1,self,NoOp,Boo!,default
1422          * New: foo = *1,self,NoOp(Boo!),default
1423          *
1424          * We need to handle both
1425          */
1426         paren = strchr(args.app, '(');
1427         if (paren) {
1428                 /* New syntax */
1429                 char *close_paren;
1430
1431                 args.moh_class = args.app_data;
1432                 *paren++ = '\0';
1433                 close_paren = strrchr(paren, ')');
1434                 if (close_paren) {
1435                         *close_paren = '\0';
1436                 }
1437                 args.app_data = paren;
1438
1439                 /* Re-check that the application is not empty */
1440                 if (ast_strlen_zero(args.app)) {
1441                         ast_log(LOG_WARNING, "Applicationmap item '%s' does not contain an application name.\n", var->name);
1442                         return -1;
1443                 }
1444         } else if (strchr(args.app_data, '"')) {
1445                 args.app_data = ast_strip_quoted(args.app_data, "\"", "\"");
1446         }
1447
1448         /* Allow caller and callee to be specified for backwards compatibility */
1449         if (!strcasecmp(args.activate_on, "self") || !strcasecmp(args.activate_on, "caller")) {
1450                 activate_on_self = 1;
1451         } else if (!strcasecmp(args.activate_on, "peer") || !strcasecmp(args.activate_on, "callee")) {
1452                 activate_on_self = 0;
1453         } else {
1454                 ast_log(LOG_WARNING, "Invalid 'activate_on' value %s for applicationmap item %s\n",
1455                         args.activate_on, var->name);
1456                 return -1;
1457         }
1458
1459         ast_debug(1, "Allocating applicationmap item: dtmf = %s, app = %s, app_data = %s, moh_class = %s\n",
1460                         args.dtmf, args.app, args.app_data, args.moh_class);
1461
1462         item = applicationmap_item_alloc(var->name, args.app, args.app_data,
1463                         args.moh_class, args.dtmf, activate_on_self);
1464
1465         if (!item) {
1466                 return -1;
1467         }
1468
1469         if (!ao2_link(applicationmap, item)) {
1470                 return -1;
1471         }
1472
1473         return 0;
1474 }
1475
1476 static int featuregroup_handler(const struct aco_option *opt,
1477                 struct ast_variable *var, void *obj)
1478 {
1479         RAII_VAR(struct featuregroup_item *, item, NULL, ao2_cleanup);
1480         struct featuregroup *group = obj;
1481
1482         item = ao2_alloc(sizeof(*item), featuregroup_item_destructor);
1483         if (!item || ast_string_field_init(item, 32)) {
1484                 return -1;
1485         }
1486
1487         ast_string_field_set(item, appmap_item_name, var->name);
1488         ast_string_field_set(item, dtmf_override, var->value);
1489
1490         if (!ao2_link(group->items, item)) {
1491                 return -1;
1492         }
1493
1494         /* We wait to look up the application map item in the preapply callback */
1495
1496         return 0;
1497 }
1498
1499 static int general_handler(const struct aco_option *opt,
1500                 struct ast_variable *var, void *obj)
1501 {
1502         struct features_global_config *global = obj;
1503         struct ast_features_general_config *general = global->general;
1504
1505         return general_set(general, var->name, var->value);
1506 }
1507
1508 static int xfer_handler(const struct aco_option *opt,
1509                 struct ast_variable *var, void *obj)
1510 {
1511         struct features_global_config *global = obj;
1512         struct ast_features_xfer_config *xfer = global->xfer;
1513
1514         return xfer_set(xfer, var->name, var->value);
1515 }
1516
1517 static int pickup_handler(const struct aco_option *opt,
1518                 struct ast_variable *var, void *obj)
1519 {
1520         struct features_global_config *global = obj;
1521         struct ast_features_pickup_config *pickup = global->pickup;
1522
1523         return pickup_set(pickup, var->name, var->value);
1524 }
1525
1526 static int parking_warning = 0;
1527 static int unsupported_handler(const struct aco_option *opt,
1528                 struct ast_variable *var, void *obj)
1529 {
1530         if (!parking_warning) {
1531                 ast_log(LOG_WARNING, "Parkinglots are no longer configurable in features.conf; "
1532                         "parking is now handled by res_parking.conf\n");
1533                 parking_warning = 1;
1534         }
1535         ast_log(LOG_WARNING, "The option '%s' is no longer configurable in features.conf.\n", var->name);
1536         return 0;
1537 }
1538
1539 static int featuremap_handler(const struct aco_option *opt,
1540                 struct ast_variable *var, void *obj)
1541 {
1542         struct ast_featuremap_config *featuremap = obj;
1543
1544         return featuremap_set(featuremap, var->name, var->value);
1545 }
1546
1547 static int check_featuregroup_item(void *obj, void *arg, void *data, int flags)
1548 {
1549         struct ast_applicationmap_item *appmap_item;
1550         struct featuregroup_item *fg_item = obj;
1551         int *err = arg;
1552         struct ao2_container *applicationmap = data;
1553
1554         appmap_item = ao2_find(applicationmap, fg_item->appmap_item_name, OBJ_KEY);
1555         if (!appmap_item) {
1556                 *err = 1;
1557                 return CMP_STOP;
1558         }
1559
1560         fg_item->appmap_item = appmap_item;
1561
1562         return 0;
1563 }
1564
1565 static int check_featuregroup(void *obj, void *arg, void *data, int flags)
1566 {
1567         struct featuregroup *group = obj;
1568         int *err = arg;
1569
1570         ao2_callback_data(group->items, 0, check_featuregroup_item, arg, data);
1571
1572         if (*err) {
1573                 ast_log(LOG_WARNING, "Featuregroup %s refers to non-existent applicationmap item\n",
1574                                 group->name);
1575         }
1576
1577         return *err ? CMP_STOP : 0;
1578 }
1579
1580 static int features_pre_apply_config(void);
1581
1582 CONFIG_INFO_CORE("features", cfg_info, globals, features_config_alloc,
1583         .files = ACO_FILES(&features_conf),
1584         .pre_apply_config = features_pre_apply_config,
1585 );
1586
1587 static int features_pre_apply_config(void)
1588 {
1589         struct features_config *cfg = aco_pending_config(&cfg_info);
1590         int err = 0;
1591
1592         /* Now that the entire config has been processed, we can check that the featuregroup
1593          * items refer to actual applicationmap items.
1594          */
1595
1596         /* global config must be initialized */
1597         ast_assert(cfg->featuregroups != NULL);
1598         ast_assert(cfg->applicationmap != NULL);
1599         ao2_callback_data(cfg->featuregroups, 0, check_featuregroup, &err, cfg->applicationmap);
1600
1601         return err;
1602 }
1603
1604 static int internal_feature_read(struct ast_channel *chan, const char *cmd, char *data,
1605                char *buf, size_t len)
1606 {
1607         int res;
1608         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1609         SCOPED_CHANNELLOCK(lock, chan);
1610
1611         if (!strcasecmp(data, "inherit")) {
1612                 struct ast_datastore *ds = get_feature_chan_ds(chan);
1613                 unsigned int inherit = ds ? ds->inheritance : 0;
1614
1615                 snprintf(buf, len, "%s", inherit ? "yes" : "no");
1616                 return 0;
1617         }
1618
1619         cfg = get_feature_ds(chan);
1620         if (!cfg) {
1621                 return -1;
1622         }
1623
1624         res = general_get(cfg->global->general, data, buf, len) &&
1625                 xfer_get(cfg->global->xfer, data, buf, len) &&
1626                 pickup_get(cfg->global->pickup, data, buf, len);
1627
1628         if (res) {
1629                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
1630         }
1631
1632         return res;
1633 }
1634
1635 static int internal_feature_write(struct ast_channel *chan, const char *cmd, char *data,
1636                 const char *value)
1637 {
1638         int res;
1639         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1640         SCOPED_CHANNELLOCK(lock, chan);
1641
1642         if (!strcasecmp(data, "inherit")) {
1643                 struct ast_datastore *ds = get_feature_chan_ds(chan);
1644                 if (ds) {
1645                         ds->inheritance = ast_true(value) ? DATASTORE_INHERIT_FOREVER : 0;
1646                 }
1647                 return 0;
1648         }
1649
1650         if (!(cfg = get_feature_ds(chan))) {
1651                 return -1;
1652         }
1653
1654         res = general_set(cfg->global->general, data, value) &&
1655                 xfer_set(cfg->global->xfer, data, value) &&
1656                 pickup_set(cfg->global->pickup, data, value);
1657
1658         if (res) {
1659                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
1660         }
1661
1662         return res;
1663 }
1664
1665 static int internal_featuremap_read(struct ast_channel *chan, const char *cmd, char *data,
1666                char *buf, size_t len)
1667 {
1668         int res;
1669         SCOPED_CHANNELLOCK(lock, chan);
1670
1671         res = ast_get_builtin_feature(chan, data, buf, len);
1672
1673         if (res) {
1674                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATUREMAP()\n", data);
1675         }
1676
1677         return res;
1678 }
1679
1680 static int internal_featuremap_write(struct ast_channel *chan, const char *cmd, char *data,
1681                 const char *value)
1682 {
1683         int res;
1684         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1685         SCOPED_CHANNELLOCK(lock, chan);
1686
1687         if (!(cfg = get_feature_ds(chan))) {
1688                 return -1;
1689         }
1690
1691         res = featuremap_set(cfg->featuremap, data, value);
1692         if (res) {
1693                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATUREMAP()\n", data);
1694                 return -1;
1695         }
1696
1697         return 0;
1698 }
1699
1700 static int feature_read(struct ast_channel *chan, const char *cmd, char *data,
1701                 char *buf, size_t len)
1702 {
1703         if (!chan) {
1704                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1705                 return -1;
1706         }
1707
1708         return internal_feature_read(chan, cmd, data, buf, len);
1709 }
1710
1711 static int feature_write(struct ast_channel *chan, const char *cmd, char *data,
1712                 const char *value)
1713 {
1714         if (!chan) {
1715                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1716                 return -1;
1717         }
1718
1719         return internal_feature_write(chan, cmd, data, value);
1720 }
1721
1722 static int featuremap_read(struct ast_channel *chan, const char *cmd, char *data,
1723                 char *buf, size_t len)
1724 {
1725         if (!chan) {
1726                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1727                 return -1;
1728         }
1729
1730         return internal_featuremap_read(chan, cmd, data, buf, len);
1731 }
1732
1733 static int featuremap_write(struct ast_channel *chan, const char *cmd, char *data,
1734                 const char *value)
1735 {
1736         if (!chan) {
1737                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
1738                 return -1;
1739         }
1740
1741         return internal_featuremap_write(chan, cmd, data, value);
1742 }
1743
1744 static struct ast_custom_function feature_function = {
1745         .name = "FEATURE",
1746         .read = feature_read,
1747         .write = feature_write
1748 };
1749
1750 static struct ast_custom_function featuremap_function = {
1751         .name = "FEATUREMAP",
1752         .read = featuremap_read,
1753         .write = featuremap_write
1754 };
1755
1756 static int load_config(void)
1757 {
1758         if (aco_info_init(&cfg_info)) {
1759                 ast_log(LOG_ERROR, "Unable to initialize configuration info for features\n");
1760                 return -1;
1761         }
1762
1763         aco_option_register_custom(&cfg_info, "featuredigittimeout", ACO_EXACT, global_options,
1764                         __stringify(DEFAULT_FEATURE_DIGIT_TIMEOUT), general_handler, 0);
1765         aco_option_register_custom(&cfg_info, "recordingfailsound", ACO_EXACT, global_options,
1766                         DEFAULT_RECORDING_FAIL_SOUND, general_handler, 0);
1767         aco_option_register_custom(&cfg_info, "courtesytone", ACO_EXACT, global_options,
1768                         DEFAULT_COURTESY_TONE, general_handler, 0);
1769
1770         aco_option_register_custom(&cfg_info, "transferdigittimeout", ACO_EXACT, global_options,
1771                         __stringify(DEFAULT_TRANSFER_DIGIT_TIMEOUT), xfer_handler, 0)
1772         aco_option_register_custom(&cfg_info, "atxfernoanswertimeout", ACO_EXACT, global_options,
1773                         __stringify(DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER), xfer_handler, 0);
1774         aco_option_register_custom(&cfg_info, "atxferdropcall", ACO_EXACT, global_options,
1775                         __stringify(DEFAULT_ATXFER_DROP_CALL), xfer_handler, 0);
1776         aco_option_register_custom(&cfg_info, "atxferloopdelay", ACO_EXACT, global_options,
1777                         __stringify(DEFAULT_ATXFER_LOOP_DELAY), xfer_handler, 0);
1778         aco_option_register_custom(&cfg_info, "atxfercallbackretries", ACO_EXACT, global_options,
1779                         __stringify(DEFAULT_ATXFER_CALLBACK_RETRIES), xfer_handler, 0);
1780         aco_option_register_custom(&cfg_info, "xfersound", ACO_EXACT, global_options,
1781                         DEFAULT_XFERSOUND, xfer_handler, 0);
1782         aco_option_register_custom(&cfg_info, "xferfailsound", ACO_EXACT, global_options,
1783                         DEFAULT_XFERFAILSOUND, xfer_handler, 0);
1784         aco_option_register_custom(&cfg_info, "atxferabort", ACO_EXACT, global_options,
1785                         DEFAULT_ATXFER_ABORT, xfer_handler, 0);
1786         aco_option_register_custom(&cfg_info, "atxfercomplete", ACO_EXACT, global_options,
1787                         DEFAULT_ATXFER_COMPLETE, xfer_handler, 0);
1788         aco_option_register_custom(&cfg_info, "atxferthreeway", ACO_EXACT, global_options,
1789                         DEFAULT_ATXFER_THREEWAY, xfer_handler, 0);
1790         aco_option_register_custom(&cfg_info, "atxferswap", ACO_EXACT, global_options,
1791                         DEFAULT_ATXFER_SWAP, xfer_handler, 0);
1792         aco_option_register_custom(&cfg_info, "transferdialattempts", ACO_EXACT, global_options,
1793                         __stringify(DEFAULT_TRANSFER_DIAL_ATTEMPTS), xfer_handler, 0);
1794         aco_option_register_custom(&cfg_info, "transferretrysound", ACO_EXACT, global_options,
1795                         DEFAULT_TRANSFER_RETRY_SOUND, xfer_handler, 0);
1796         aco_option_register_custom(&cfg_info, "transferinvalidsound", ACO_EXACT, global_options,
1797                         DEFAULT_TRANSFER_INVALID_SOUND, xfer_handler, 0);
1798
1799         aco_option_register_custom(&cfg_info, "pickupexten", ACO_EXACT, global_options,
1800                         DEFAULT_PICKUPEXTEN, pickup_handler, 0);
1801         aco_option_register_custom(&cfg_info, "pickupsound", ACO_EXACT, global_options,
1802                         DEFAULT_PICKUPSOUND, pickup_handler, 0);
1803         aco_option_register_custom(&cfg_info, "pickupfailsound", ACO_EXACT, global_options,
1804                         DEFAULT_PICKUPFAILSOUND, pickup_handler, 0);
1805
1806         aco_option_register_custom_nodoc(&cfg_info, "context", ACO_EXACT, global_options,
1807                         "", unsupported_handler, 0);
1808         aco_option_register_custom_nodoc(&cfg_info, "parkext", ACO_EXACT, global_options,
1809                         "", unsupported_handler, 0);
1810         aco_option_register_custom_nodoc(&cfg_info, "parkext_exclusive", ACO_EXACT, global_options,
1811                         "", unsupported_handler, 0);
1812         aco_option_register_custom_nodoc(&cfg_info, "parkinghints", ACO_EXACT, global_options,
1813                         "", unsupported_handler, 0);
1814         aco_option_register_custom_nodoc(&cfg_info, "parkedmusicclass", ACO_EXACT, global_options,
1815                         "", unsupported_handler, 0);
1816         aco_option_register_custom_nodoc(&cfg_info, "parkingtime", ACO_EXACT, global_options,
1817                         "", unsupported_handler, 0);
1818         aco_option_register_custom_nodoc(&cfg_info, "parkpos", ACO_EXACT, global_options,
1819                         "", unsupported_handler, 0);
1820         aco_option_register_custom_nodoc(&cfg_info, "findslot", ACO_EXACT, global_options,
1821                         "", unsupported_handler, 0);
1822         aco_option_register_custom_nodoc(&cfg_info, "parkedcalltransfers", ACO_EXACT, global_options,
1823                         "", unsupported_handler, 0);
1824         aco_option_register_custom_nodoc(&cfg_info, "parkedcallreparking", ACO_EXACT, global_options,
1825                         "", unsupported_handler, 0);
1826         aco_option_register_custom_nodoc(&cfg_info, "parkedcallhangup", ACO_EXACT, global_options,
1827                         "", unsupported_handler, 0);
1828         aco_option_register_custom_nodoc(&cfg_info, "parkedcallrecording", ACO_EXACT, global_options,
1829                         "", unsupported_handler, 0);
1830         aco_option_register_custom_nodoc(&cfg_info, "comebackcontext", ACO_EXACT, global_options,
1831                         "", unsupported_handler, 0);
1832         aco_option_register_custom_nodoc(&cfg_info, "comebacktoorigin", ACO_EXACT, global_options,
1833                         "", unsupported_handler, 0);
1834         aco_option_register_custom_nodoc(&cfg_info, "comebackdialtime", ACO_EXACT, global_options,
1835                         "", unsupported_handler, 0);
1836         aco_option_register_custom_nodoc(&cfg_info, "parkeddynamic", ACO_EXACT, global_options,
1837                         "", unsupported_handler, 0);
1838         aco_option_register_custom_nodoc(&cfg_info, "adsipark", ACO_EXACT, global_options,
1839                         "", unsupported_handler, 0);
1840
1841         aco_option_register_custom(&cfg_info, "blindxfer", ACO_EXACT, featuremap_options,
1842                         DEFAULT_FEATUREMAP_BLINDXFER, featuremap_handler, 0);
1843         aco_option_register_custom(&cfg_info, "disconnect", ACO_EXACT, featuremap_options,
1844                         DEFAULT_FEATUREMAP_DISCONNECT, featuremap_handler, 0);
1845         aco_option_register_custom(&cfg_info, "automon", ACO_EXACT, featuremap_options,
1846                         DEFAULT_FEATUREMAP_AUTOMON, featuremap_handler, 0);
1847         aco_option_register_custom(&cfg_info, "atxfer", ACO_EXACT, featuremap_options,
1848                         DEFAULT_FEATUREMAP_ATXFER, featuremap_handler, 0);
1849         aco_option_register_custom(&cfg_info, "parkcall", ACO_EXACT, featuremap_options,
1850                         DEFAULT_FEATUREMAP_PARKCALL, featuremap_handler, 0);
1851         aco_option_register_custom(&cfg_info, "automixmon", ACO_EXACT, featuremap_options,
1852                         DEFAULT_FEATUREMAP_AUTOMIXMON, featuremap_handler, 0);
1853
1854         aco_option_register_custom(&cfg_info, "", ACO_PREFIX, applicationmap_options,
1855                         "", applicationmap_handler, 0);
1856
1857         aco_option_register_custom(&cfg_info, "", ACO_PREFIX, featuregroup_options,
1858                         "", featuregroup_handler, 0);
1859
1860         aco_option_register_custom_nodoc(&cfg_info, "", ACO_PREFIX, parkinglot_options,
1861                         "", unsupported_handler, 0);
1862
1863         if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
1864                 RAII_VAR(struct features_config *, features_cfg, features_config_alloc(), ao2_cleanup);
1865
1866                 if (aco_set_defaults(&global_option, "general", features_cfg->global) ||
1867                         aco_set_defaults(&featuremap_option, "featuremap", features_cfg->featuremap)) {
1868                         ast_log(LOG_ERROR, "Failed to load features.conf and failed to initialize defaults.\n");
1869                         return -1;
1870                 }
1871
1872                 ast_log(LOG_NOTICE, "Could not load features config; using defaults\n");
1873                 ao2_global_obj_replace_unref(globals, features_cfg);
1874         }
1875
1876         return 0;
1877 }
1878
1879 static int print_featuregroup(void *obj, void *arg, int flags)
1880 {
1881         struct featuregroup_item *item = obj;
1882         struct ast_cli_args *a = arg;
1883
1884         ast_cli(a->fd, "===> --> %s (%s)\n", item->appmap_item_name,
1885                         S_OR(item->dtmf_override, item->appmap_item->dtmf));
1886
1887         return 0;
1888 }
1889
1890 static int print_featuregroups(void *obj, void *arg, int flags)
1891 {
1892         struct featuregroup *group = obj;
1893         struct ast_cli_args *a = arg;
1894
1895         ast_cli(a->fd, "===> Group: %s\n", group->name);
1896
1897         ao2_callback(group->items, 0, print_featuregroup, a);
1898         return 0;
1899 }
1900
1901 #define HFS_FORMAT "%-25s %-7s %-7s\n"
1902
1903 static int print_applicationmap(void *obj, void *arg, int flags)
1904 {
1905         struct ast_applicationmap_item *item = obj;
1906         struct ast_cli_args *a = arg;
1907
1908         ast_cli(a->fd, HFS_FORMAT, item->name, "no def", item->dtmf);
1909         return 0;
1910 }
1911
1912 /*!
1913  * \brief CLI command to list configured features
1914  * \param e
1915  * \param cmd
1916  * \param a
1917  *
1918  * \retval CLI_SUCCESS on success.
1919  * \retval NULL when tab completion is used.
1920  */
1921 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1922 {
1923         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1924
1925         switch (cmd) {
1926
1927         case CLI_INIT:
1928                 e->command = "features show";
1929                 e->usage =
1930                         "Usage: features show\n"
1931                         "       Lists configured features\n";
1932                 return NULL;
1933         case CLI_GENERATE:
1934                 return NULL;
1935         }
1936
1937         cfg = ao2_global_obj_ref(globals);
1938
1939         ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
1940         ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
1941
1942         ast_cli(a->fd, HFS_FORMAT, "Pickup", DEFAULT_PICKUPEXTEN, cfg->global->pickup->pickupexten);
1943         ast_cli(a->fd, HFS_FORMAT, "Blind Transfer", DEFAULT_FEATUREMAP_BLINDXFER, cfg->featuremap->blindxfer);
1944         ast_cli(a->fd, HFS_FORMAT, "Attended Transfer", DEFAULT_FEATUREMAP_ATXFER, cfg->featuremap->atxfer);
1945         ast_cli(a->fd, HFS_FORMAT, "One Touch Monitor", DEFAULT_FEATUREMAP_AUTOMON, cfg->featuremap->automon);
1946         ast_cli(a->fd, HFS_FORMAT, "Disconnect Call", DEFAULT_FEATUREMAP_DISCONNECT, cfg->featuremap->disconnect);
1947         ast_cli(a->fd, HFS_FORMAT, "Park Call", DEFAULT_FEATUREMAP_PARKCALL, cfg->featuremap->parkcall);
1948         ast_cli(a->fd, HFS_FORMAT, "One Touch MixMonitor", DEFAULT_FEATUREMAP_AUTOMIXMON, cfg->featuremap->automixmon);
1949
1950         ast_cli(a->fd, "\n");
1951         ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
1952         ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
1953         if (!cfg->applicationmap || ao2_container_count(cfg->applicationmap) == 0) {
1954                 ast_cli(a->fd, "(none)\n");
1955         } else {
1956                 ao2_callback(cfg->applicationmap, 0, print_applicationmap, a);
1957         }
1958
1959         ast_cli(a->fd, "\nFeature Groups:\n");
1960         ast_cli(a->fd, "---------------\n");
1961         if (!cfg->featuregroups || ao2_container_count(cfg->featuregroups) == 0) {
1962                 ast_cli(a->fd, "(none)\n");
1963         } else {
1964                 ao2_callback(cfg->featuregroups, 0, print_featuregroups, a);
1965         }
1966
1967         return CLI_SUCCESS;
1968 }
1969
1970 static struct ast_cli_entry cli_features_config[] = {
1971         AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
1972 };
1973
1974 void ast_features_config_shutdown(void)
1975 {
1976         ast_custom_function_unregister(&featuremap_function);
1977         ast_custom_function_unregister(&feature_function);
1978         ast_cli_unregister_multiple(cli_features_config, ARRAY_LEN(cli_features_config));
1979         aco_info_destroy(&cfg_info);
1980         ao2_global_obj_release(globals);
1981 }
1982
1983 int ast_features_config_reload(void)
1984 {
1985         /* Rearm the parking config options have moved warning. */
1986         parking_warning = 0;
1987
1988         if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
1989                 return -1;
1990         }
1991         return 0;
1992 }
1993
1994 int ast_features_config_init(void)
1995 {
1996         int res;
1997
1998         res = load_config();
1999         res |= __ast_custom_function_register(&feature_function, NULL);
2000         res |= __ast_custom_function_register(&featuremap_function, NULL);
2001         res |= ast_cli_register_multiple(cli_features_config, ARRAY_LEN(cli_features_config));
2002
2003         if (res) {
2004                 ast_features_config_shutdown();
2005         }
2006
2007         return res;
2008 }