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