91e7df338a9244217970b40e31b288283222f061
[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->applicationmap);
626         ao2_cleanup(cfg->featuregroups);
627 }
628
629 static void featuremap_config_destructor(void *obj)
630 {
631         struct ast_featuremap_config *cfg = obj;
632
633         ast_string_field_free_memory(cfg);
634 }
635
636 static void global_config_destructor(void *obj)
637 {
638         struct features_global_config *cfg = obj;
639
640         ao2_cleanup(cfg->general);
641         ao2_cleanup(cfg->xfer);
642         ao2_cleanup(cfg->pickup);
643 }
644
645 static void general_destructor(void *obj)
646 {
647         struct ast_features_general_config *cfg = obj;
648
649         ast_string_field_free_memory(cfg);
650 }
651
652 static void xfer_destructor(void *obj)
653 {
654         struct ast_features_xfer_config *cfg = obj;
655
656         ast_string_field_free_memory(cfg);
657 }
658
659 static void pickup_destructor(void *obj)
660 {
661         struct ast_features_pickup_config *cfg = obj;
662
663         ast_string_field_free_memory(cfg);
664 }
665
666 static struct features_global_config *global_config_alloc(void)
667 {
668         RAII_VAR(struct features_global_config *, cfg, NULL, ao2_cleanup);
669
670         cfg = ao2_alloc(sizeof(*cfg), global_config_destructor);
671         if (!cfg) {
672                 return NULL;
673         }
674
675         cfg->general = ao2_alloc(sizeof(*cfg->general), general_destructor);
676         if (!cfg->general || ast_string_field_init(cfg->general, 32)) {
677                 return NULL;
678         }
679
680         cfg->xfer = ao2_alloc(sizeof(*cfg->xfer), xfer_destructor);
681         if (!cfg->xfer || ast_string_field_init(cfg->xfer, 32)) {
682                 return NULL;
683         }
684
685         cfg->pickup = ao2_alloc(sizeof(*cfg->pickup), pickup_destructor);
686         if (!cfg->pickup || ast_string_field_init(cfg->pickup, 32)) {
687                 return NULL;
688         }
689
690         ao2_ref(cfg, +1);
691         return cfg;
692 }
693
694 static struct ao2_container *applicationmap_alloc(int replace_duplicates)
695 {
696         return ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
697                 replace_duplicates ? AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE : AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW,
698                 applicationmap_sort, NULL);
699 }
700
701 /*!
702  * \internal
703  * \brief Allocate the major configuration structure
704  *
705  * The parameter is used to determine if the applicationmap and featuregroup
706  * structures should be allocated. We only want to allocate these structures for
707  * the global features_config structure. For the datastores on channels, we don't
708  * need to allocate these structures because they are not used.
709  *
710  * \param allocate_applicationmap See previous explanation
711  * \retval NULL Failed to alloate configuration
712  * \retval non-NULL Allocated configuration
713  */
714 static struct features_config *__features_config_alloc(int allocate_applicationmap)
715 {
716         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
717
718         cfg = ao2_alloc(sizeof(*cfg), features_config_destructor);
719         if (!cfg) {
720                 return NULL;
721         }
722
723         cfg->global = global_config_alloc();;
724         if (!cfg->global) {
725                 return NULL;
726         }
727
728         cfg->featuremap = ao2_alloc(sizeof(*cfg->featuremap), featuremap_config_destructor);
729         if (!cfg->featuremap || ast_string_field_init(cfg->featuremap, 32)) {
730                 return NULL;
731         }
732
733         cfg->parkinglots = ao2_alloc(sizeof(*cfg->parkinglots), NULL);
734         if (!cfg->parkinglots) {
735                 return NULL;
736         }
737
738         if (allocate_applicationmap) {
739                 cfg->applicationmap = applicationmap_alloc(1);
740                 if (!cfg->applicationmap) {
741                         return NULL;
742                 }
743
744                 cfg->featuregroups = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 11, featuregroup_hash,
745                         featuregroup_cmp);
746                 if (!cfg->featuregroups) {
747                         return NULL;
748                 }
749         }
750
751         ao2_ref(cfg, +1);
752         return cfg;
753
754 }
755
756 static void *features_config_alloc(void)
757 {
758         return __features_config_alloc(1);
759 }
760
761 static void general_copy(struct ast_features_general_config *dest, const struct ast_features_general_config *src)
762 {
763         ast_string_fields_copy(dest, src);
764         dest->featuredigittimeout = src->featuredigittimeout;
765 }
766
767 static void xfer_copy(struct ast_features_xfer_config *dest, const struct ast_features_xfer_config *src)
768 {
769         ast_string_fields_copy(dest, src);
770         dest->transferdigittimeout = src->transferdigittimeout;
771         dest->atxfernoanswertimeout = src->atxfernoanswertimeout;
772         dest->atxferloopdelay = src->atxferloopdelay;
773         dest->atxfercallbackretries = src->atxfercallbackretries;
774         dest->atxferdropcall = src->atxferdropcall;
775 }
776
777 static void pickup_copy(struct ast_features_pickup_config *dest, const struct ast_features_pickup_config *src)
778 {
779         ast_string_fields_copy(dest, src);
780 }
781
782 static void global_copy(struct features_global_config *dest, const struct features_global_config *src)
783 {
784         general_copy(dest->general, src->general);
785         xfer_copy(dest->xfer, src->xfer);
786         pickup_copy(dest->pickup, src->pickup);
787 }
788
789 static void featuremap_copy(struct ast_featuremap_config *dest, const struct ast_featuremap_config *src)
790 {
791         ast_string_fields_copy(dest, src);
792 }
793
794 static void features_copy(struct features_config *dest, const struct features_config *src)
795 {
796         global_copy(dest->global, src->global);
797         featuremap_copy(dest->featuremap, src->featuremap);
798
799         /* applicationmap and featuregroups are purposely not copied. A channel's applicationmap
800          * is produced on the fly when ast_get_chan_applicationmap() is called
801          */
802 }
803
804 static struct features_config *features_config_dup(const struct features_config *orig)
805 {
806         struct features_config *dup;
807
808         dup = __features_config_alloc(0);
809         if (!dup) {
810                 return NULL;
811         }
812
813         features_copy(dup, orig);
814
815         return dup;
816 }
817
818 static int general_set(struct ast_features_general_config *general, const char *name,
819                 const char *value)
820 {
821         int res = 0;
822
823         if (!strcasecmp(name, "featuredigittimeout")) {
824                 res = ast_parse_arg(value, PARSE_INT32, &general->featuredigittimeout);
825         } else if (!strcasecmp(name, "courtesytone")) {
826                 ast_string_field_set(general, courtesytone, value);
827         } else if (!strcasecmp(name, "recordingfailsound")) {
828                 ast_string_field_set(general, recordingfailsound, value);
829         } else {
830                 /* Unrecognized option */
831                 res = -1;
832         }
833
834         return res;
835 }
836
837 static int general_get(struct ast_features_general_config *general, const char *field,
838                 char *buf, size_t len)
839 {
840         int res = 0;
841
842         if (!strcasecmp(field, "featuredigittimeout")) {
843                 snprintf(buf, len, "%u", general->featuredigittimeout);
844         } else if (!strcasecmp(field, "courtesytone")) {
845                 ast_copy_string(buf, general->courtesytone, len);
846         } else if (!strcasecmp(field, "recordingfailsound")) {
847                 ast_copy_string(buf, general->recordingfailsound, len);
848         } else {
849                 /* Unrecognized option */
850                 res = -1;
851         }
852
853         return res;
854 }
855
856 static int xfer_set(struct ast_features_xfer_config *xfer, const char *name,
857                 const char *value)
858 {
859         int res = 0;
860
861         if (!strcasecmp(name, "transferdigittimeout")) {
862                 res = ast_parse_arg(value, PARSE_INT32, &xfer->transferdigittimeout);
863         } else if (!strcasecmp(name, "atxfernoanswertimeout")) {
864                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxfernoanswertimeout);
865         } else if (!strcasecmp(name, "atxferloopdelay")) {
866                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxferloopdelay);
867         } else if (!strcasecmp(name, "atxfercallbackretries")) {
868                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxfercallbackretries);
869         } else if (!strcasecmp(name, "atxferdropcall")) {
870                 xfer->atxferdropcall = ast_true(value);
871         } else if (!strcasecmp(name, "xfersound")) {
872                 ast_string_field_set(xfer, xfersound, value);
873         } else if (!strcasecmp(name, "xferfailsound")) {
874                 ast_string_field_set(xfer, xferfailsound, value);
875         } else if (!strcasecmp(name, "atxferabort")) {
876                 ast_string_field_set(xfer, atxferabort, value);
877         } else if (!strcasecmp(name, "atxfercomplete")) {
878                 ast_string_field_set(xfer, atxfercomplete, value);
879         } else if (!strcasecmp(name, "atxferthreeway")) {
880                 ast_string_field_set(xfer, atxferthreeway, value);
881         } else if (!strcasecmp(name, "atxferswap")) {
882                 ast_string_field_set(xfer, atxferswap, value);
883         } else {
884                 /* Unrecognized option */
885                 res = -1;
886         }
887
888         return res;
889 }
890
891 static int xfer_get(struct ast_features_xfer_config *xfer, const char *field,
892                 char *buf, size_t len)
893 {
894         int res = 0;
895
896         if (!strcasecmp(field, "transferdigittimeout")) {
897                 snprintf(buf, len, "%u", xfer->transferdigittimeout);
898         } else if (!strcasecmp(field, "atxfernoanswertimeout")) {
899                 snprintf(buf, len, "%u", xfer->atxfernoanswertimeout);
900         } else if (!strcasecmp(field, "atxferloopdelay")) {
901                 snprintf(buf, len, "%u", xfer->atxferloopdelay);
902         } else if (!strcasecmp(field, "atxfercallbackretries")) {
903                 snprintf(buf, len, "%u", xfer->atxfercallbackretries);
904         } else if (!strcasecmp(field, "atxferdropcall")) {
905                 snprintf(buf, len, "%u", xfer->atxferdropcall);
906         } else if (!strcasecmp(field, "xfersound")) {
907                 ast_copy_string(buf, xfer->xfersound, len);
908         } else if (!strcasecmp(field, "xferfailsound")) {
909                 ast_copy_string(buf, xfer->xferfailsound, len);
910         } else if (!strcasecmp(field, "atxferabort")) {
911                 ast_copy_string(buf, xfer->atxferabort, len);
912         } else if (!strcasecmp(field, "atxfercomplete")) {
913                 ast_copy_string(buf, xfer->atxfercomplete, len);
914         } else if (!strcasecmp(field, "atxferthreeway")) {
915                 ast_copy_string(buf, xfer->atxferthreeway, len);
916         } else if (!strcasecmp(field, "atxferswap")) {
917                 ast_copy_string(buf, xfer->atxferswap, len);
918         } else {
919                 /* Unrecognized option */
920                 res = -1;
921         }
922
923         return res;
924 }
925
926 static int pickup_set(struct ast_features_pickup_config *pickup, const char *name,
927                 const char *value)
928 {
929         int res = 0;
930
931         if (!strcasecmp(name, "pickupsound")) {
932                 ast_string_field_set(pickup, pickupsound, value);
933         } else if (!strcasecmp(name, "pickupfailsound")) {
934                 ast_string_field_set(pickup, pickupfailsound, value);
935         } else if (!strcasecmp(name, "pickupexten")) {
936                 ast_string_field_set(pickup, pickupexten, value);
937         } else {
938                 /* Unrecognized option */
939                 res = -1;
940         }
941
942         return res;
943 }
944
945 static int pickup_get(struct ast_features_pickup_config *pickup, const char *field,
946                 char *buf, size_t len)
947 {
948         int res = 0;
949
950         if (!strcasecmp(field, "pickupsound")) {
951                 ast_copy_string(buf, pickup->pickupsound, len);
952         } else if (!strcasecmp(field, "pickupfailsound")) {
953                 ast_copy_string(buf, pickup->pickupfailsound, len);
954         } else if (!strcasecmp(field, "pickupexten")) {
955                 ast_copy_string(buf, pickup->pickupexten, len);
956         } else {
957                 /* Unrecognized option */
958                 res = -1;
959         }
960
961         return res;
962 }
963
964 static int featuremap_set(struct ast_featuremap_config *featuremap, const char *name,
965                 const char *value)
966 {
967         int res = 0;
968
969         if (!strcasecmp(name, "blindxfer")) {
970                 ast_string_field_set(featuremap, blindxfer, value);
971         } else if (!strcasecmp(name, "disconnect")) {
972                 ast_string_field_set(featuremap, disconnect, value);
973         } else if (!strcasecmp(name, "automon")) {
974                 ast_string_field_set(featuremap, automon, value);
975         } else if (!strcasecmp(name, "atxfer")) {
976                 ast_string_field_set(featuremap, atxfer, value);
977         } else if (!strcasecmp(name, "automixmon")) {
978                 ast_string_field_set(featuremap, automixmon, value);
979         } else if (!strcasecmp(name, "parkcall")) {
980                 ast_string_field_set(featuremap, parkcall, value);
981         } else {
982                 /* Unrecognized option */
983                 res = -1;
984         }
985
986         return res;
987 }
988
989 static int featuremap_get(struct ast_featuremap_config *featuremap, const char *field,
990                 char *buf, size_t len)
991 {
992         int res = 0;
993
994         if (!strcasecmp(field, "blindxfer")) {
995                 ast_copy_string(buf, featuremap->blindxfer, len);
996         } else if (!strcasecmp(field, "disconnect")) {
997                 ast_copy_string(buf, featuremap->disconnect, len);
998         } else if (!strcasecmp(field, "automon")) {
999                 ast_copy_string(buf, featuremap->automon, len);
1000         } else if (!strcasecmp(field, "atxfer")) {
1001                 ast_copy_string(buf, featuremap->atxfer, len);
1002         } else if (!strcasecmp(field, "automixmon")) {
1003                 ast_copy_string(buf, featuremap->automixmon, len);
1004         } else if (!strcasecmp(field, "parkcall")) {
1005                 ast_copy_string(buf, featuremap->parkcall, len);
1006         } else {
1007                 /* Unrecognized option */
1008                 res = -1;
1009         }
1010
1011         return res;
1012 }
1013
1014 static void feature_ds_destroy(void *data)
1015 {
1016         struct features_config *cfg = data;
1017         ao2_cleanup(cfg);
1018 }
1019
1020 static void *feature_ds_duplicate(void *data)
1021 {
1022         struct features_config *old_cfg = data;
1023
1024         return features_config_dup(old_cfg);
1025 }
1026
1027 static const struct ast_datastore_info feature_ds_info = {
1028         .type = "FEATURE",
1029         .destroy = feature_ds_destroy,
1030         .duplicate = feature_ds_duplicate,
1031 };
1032
1033 /*!
1034  * \internal
1035  * \brief Find or create feature datastore on a channel
1036  *
1037  * \pre chan is locked
1038  *
1039  * \return the data on the FEATURE datastore, or NULL on error
1040  */
1041 static struct features_config *get_feature_ds(struct ast_channel *chan)
1042 {
1043         RAII_VAR(struct features_config *, orig, NULL, ao2_cleanup);
1044         struct features_config *cfg;
1045         struct ast_datastore *ds;
1046
1047         if ((ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL))) {
1048                 cfg = ds->data;
1049                 ao2_ref(cfg, +1);
1050                 return cfg;
1051         }
1052
1053         orig = ao2_global_obj_ref(globals);
1054         if (!orig) {
1055                 return NULL;
1056         }
1057
1058         cfg = features_config_dup(orig);
1059         if (!cfg) {
1060                 return NULL;
1061         }
1062
1063         if (!(ds = ast_datastore_alloc(&feature_ds_info, NULL))) {
1064                 ao2_cleanup(cfg);
1065                 return NULL;
1066         }
1067
1068         /* Give the datastore a reference to the config */
1069         ao2_ref(cfg, +1);
1070         ds->data = cfg;
1071
1072         ast_channel_datastore_add(chan, ds);
1073
1074         return cfg;
1075 }
1076
1077 static struct ast_datastore *get_feature_chan_ds(struct ast_channel *chan)
1078 {
1079         struct ast_datastore *ds;
1080
1081         if (!(ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL))) {
1082                 /* Hasn't been created yet.  Trigger creation. */
1083                 RAII_VAR(struct features_config *, cfg, get_feature_ds(chan), ao2_cleanup);
1084                 ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL);
1085         }
1086
1087         return ds;
1088 }
1089
1090 struct ast_features_general_config *ast_get_chan_features_general_config(struct ast_channel *chan)
1091 {
1092         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1093
1094         if (chan) {
1095                 cfg = get_feature_ds(chan);
1096         } else {
1097                 cfg = ao2_global_obj_ref(globals);
1098         }
1099
1100         if (!cfg) {
1101                 return NULL;
1102         }
1103
1104         ast_assert(cfg->global && cfg->global->general);
1105
1106         ao2_ref(cfg->global->general, +1);
1107         return cfg->global->general;
1108 }
1109
1110 struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_channel *chan)
1111 {
1112         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1113
1114         if (chan) {
1115                 cfg = get_feature_ds(chan);
1116         } else {
1117                 cfg = ao2_global_obj_ref(globals);
1118         }
1119
1120         if (!cfg) {
1121                 return NULL;
1122         }
1123
1124         ast_assert(cfg->global && cfg->global->xfer);
1125
1126         ao2_ref(cfg->global->xfer, +1);
1127         return cfg->global->xfer;
1128 }
1129
1130 struct ast_features_pickup_config *ast_get_chan_features_pickup_config(struct ast_channel *chan)
1131 {
1132         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1133
1134         if (chan) {
1135                 cfg = get_feature_ds(chan);
1136         } else {
1137                 cfg = ao2_global_obj_ref(globals);
1138         }
1139
1140         if (!cfg) {
1141                 return NULL;
1142         }
1143
1144         ast_assert(cfg->global && cfg->global->pickup);
1145
1146         ao2_ref(cfg->global->pickup, +1);
1147         return cfg->global->pickup;
1148 }
1149
1150 struct ast_featuremap_config *ast_get_chan_featuremap_config(struct ast_channel *chan)
1151 {
1152         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1153
1154         if (chan) {
1155                 cfg = get_feature_ds(chan);
1156         } else {
1157                 cfg = ao2_global_obj_ref(globals);
1158         }
1159
1160         if (!cfg) {
1161                 return NULL;
1162         }
1163
1164         ast_assert(cfg->featuremap != NULL);
1165
1166         ao2_ref(cfg->featuremap, +1);
1167         return cfg->featuremap;
1168 }
1169
1170 int ast_get_builtin_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
1171 {
1172         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1173
1174         if (chan) {
1175                 cfg = get_feature_ds(chan);
1176         } else {
1177                 cfg = ao2_global_obj_ref(globals);
1178         }
1179
1180         if (!cfg) {
1181                 return -1;
1182         }
1183
1184         return featuremap_get(cfg->featuremap, feature, buf, len);
1185 }
1186
1187 int ast_get_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
1188 {
1189         RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);
1190         RAII_VAR(struct ast_applicationmap_item *, item, NULL, ao2_cleanup);
1191
1192         if (!ast_get_builtin_feature(chan, feature, buf, len)) {
1193                 return 0;
1194         }
1195
1196         /* Dang, must be in the application map */
1197         applicationmap = ast_get_chan_applicationmap(chan);
1198         if (!applicationmap) {
1199                 return -1;
1200         }
1201
1202         item = ao2_find(applicationmap, feature, OBJ_KEY);
1203         if (!item) {
1204                 return -1;
1205         }
1206
1207         ast_copy_string(buf, item->dtmf, len);
1208         return 0;
1209 }
1210
1211 static struct ast_applicationmap_item *applicationmap_item_alloc(const char *name,
1212                 const char *app, const char *app_data, const char *moh_class, const char *dtmf,
1213                 unsigned int activate_on_self)
1214 {
1215         struct ast_applicationmap_item *item;
1216
1217         item = ao2_alloc(sizeof(*item), ast_applicationmap_item_destructor);
1218
1219         if (!item || ast_string_field_init(item, 64)) {
1220                 return NULL;
1221         }
1222
1223         ast_string_field_set(item, name, name);
1224         ast_string_field_set(item, app, app);
1225         ast_string_field_set(item, app_data, app_data);
1226         ast_string_field_set(item, moh_class, moh_class);
1227         ast_copy_string(item->dtmf, dtmf, sizeof(item->dtmf));
1228         item->activate_on_self = activate_on_self;
1229
1230         return item;
1231 }
1232
1233 static int add_item(void *obj, void *arg, int flags)
1234 {
1235         struct featuregroup_item *fg_item = obj;
1236         struct ao2_container *applicationmap = arg;
1237         RAII_VAR(struct ast_applicationmap_item *, appmap_item, NULL, ao2_cleanup);
1238
1239         /* If there's no DTMF override, then we can just link
1240          * the applicationmap item directly. Otherwise, we need
1241          * to create a copy with the DTMF override in place and
1242          * link that instead
1243          */
1244         if (ast_strlen_zero(fg_item->dtmf_override)) {
1245                 ao2_ref(fg_item->appmap_item, +1);
1246                 appmap_item = fg_item->appmap_item;
1247         } else {
1248                 appmap_item = applicationmap_item_alloc(fg_item->appmap_item_name,
1249                                 fg_item->appmap_item->app, fg_item->appmap_item->app_data,
1250                                 fg_item->appmap_item->moh_class, fg_item->dtmf_override,
1251                                 fg_item->appmap_item->activate_on_self);
1252         }
1253
1254         if (!appmap_item) {
1255                 return 0;
1256         }
1257
1258         ao2_link(applicationmap, appmap_item);
1259         return 0;
1260 }
1261
1262 struct ao2_container *ast_get_chan_applicationmap(struct ast_channel *chan)
1263 {
1264         RAII_VAR(struct features_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
1265         struct ao2_container *applicationmap;
1266         char *group_names;
1267         char *name;
1268
1269         if (!cfg) {
1270                 return NULL;
1271         }
1272
1273         if (!chan) {
1274                 if (!cfg->applicationmap || ao2_container_count(cfg->applicationmap) == 0) {
1275                         return NULL;
1276                 }
1277                 ao2_ref(cfg->applicationmap, +1);
1278                 return cfg->applicationmap;
1279         }
1280
1281         group_names = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"), ""));
1282         if (ast_strlen_zero(group_names)) {
1283                 return NULL;
1284         }
1285
1286         applicationmap = applicationmap_alloc(0);
1287         if (!applicationmap) {
1288                 return NULL;
1289         }
1290
1291         while ((name = strsep(&group_names, "#"))) {
1292                 RAII_VAR(struct featuregroup *, group, ao2_find(cfg->featuregroups, name, OBJ_KEY), ao2_cleanup);
1293
1294                 if (!group) {
1295                         RAII_VAR(struct ast_applicationmap_item *, item, ao2_find(cfg->applicationmap, name, OBJ_KEY), ao2_cleanup);
1296
1297                         if (item) {
1298                                 ao2_link(applicationmap, item);
1299                         } else {
1300                                 ast_log(LOG_WARNING, "Unknown DYNAMIC_FEATURES item '%s' on channel %s.\n",
1301                                         name, ast_channel_name(chan));
1302                         }
1303                 } else {
1304                         ao2_callback(group->items, 0, add_item, applicationmap);
1305                 }
1306         }
1307
1308         if (ao2_container_count(applicationmap) == 0) {
1309                 ao2_cleanup(applicationmap);
1310                 return NULL;
1311         }
1312
1313         return applicationmap;
1314 }
1315
1316 static int applicationmap_handler(const struct aco_option *opt,
1317                 struct ast_variable *var, void *obj)
1318 {
1319         RAII_VAR(struct ast_applicationmap_item *, item, NULL, ao2_cleanup);
1320         struct ao2_container *applicationmap = obj;
1321         AST_DECLARE_APP_ARGS(args,
1322                 AST_APP_ARG(dtmf);
1323                 AST_APP_ARG(activate_on);
1324                 AST_APP_ARG(app);
1325                 AST_APP_ARG(app_data);
1326                 AST_APP_ARG(moh_class);
1327         );
1328         char *parse = ast_strdupa(var->value);
1329         char *slash;
1330         char *paren;
1331         unsigned int activate_on_self;
1332
1333         AST_STANDARD_APP_ARGS(args, parse);
1334
1335         if (ast_strlen_zero(args.dtmf) ||
1336                         ast_strlen_zero(args.activate_on) ||
1337                         ast_strlen_zero(args.app)) {
1338                 ast_log(LOG_WARNING, "Invalid applicationmap syntax for '%s'. Missing required argument\n", var->name);
1339                 return -1;
1340         }
1341
1342         /* features.conf used to have an "activated_by" portion
1343          * in addition to activate_on. Get rid of whatever may be
1344          * there
1345          */
1346         slash = strchr(args.activate_on, '/');
1347         if (slash) {
1348                 *slash = '\0';
1349         }
1350
1351         /* Some applications do not require arguments. */
1352         if (!args.app_data) {
1353                 args.app_data = "";
1354         }
1355
1356         /* Two syntaxes allowed for applicationmap:
1357          * Old: foo = *1,self,NoOp,Boo!,default
1358          * New: foo = *1,self,NoOp(Boo!),default
1359          *
1360          * We need to handle both
1361          */
1362         paren = strchr(args.app, '(');
1363         if (paren) {
1364                 /* New syntax */
1365                 char *close_paren;
1366
1367                 args.moh_class = args.app_data;
1368                 *paren++ = '\0';
1369                 close_paren = strrchr(paren, ')');
1370                 if (close_paren) {
1371                         *close_paren = '\0';
1372                 }
1373                 args.app_data = paren;
1374
1375                 /* Re-check that the application is not empty */
1376                 if (ast_strlen_zero(args.app)) {
1377                         ast_log(LOG_WARNING, "Applicationmap item '%s' does not contain an application name.\n", var->name);
1378                         return -1;
1379                 }
1380         } else if (strchr(args.app_data, '"')) {
1381                 args.app_data = ast_strip_quoted(args.app_data, "\"", "\"");
1382         }
1383
1384         /* Allow caller and callee to be specified for backwards compatibility */
1385         if (!strcasecmp(args.activate_on, "self") || !strcasecmp(args.activate_on, "caller")) {
1386                 activate_on_self = 1;
1387         } else if (!strcasecmp(args.activate_on, "peer") || !strcasecmp(args.activate_on, "callee")) {
1388                 activate_on_self = 0;
1389         } else {
1390                 ast_log(LOG_WARNING, "Invalid 'activate_on' value %s for applicationmap item %s\n",
1391                         args.activate_on, var->name);
1392                 return -1;
1393         }
1394
1395         ast_debug(1, "Allocating applicationmap item: dtmf = %s, app = %s, app_data = %s, moh_class = %s\n",
1396                         args.dtmf, args.app, args.app_data, args.moh_class);
1397
1398         item = applicationmap_item_alloc(var->name, args.app, args.app_data,
1399                         args.moh_class, args.dtmf, activate_on_self);
1400
1401         if (!item) {
1402                 return -1;
1403         }
1404
1405         if (!ao2_link(applicationmap, item)) {
1406                 return -1;
1407         }
1408
1409         return 0;
1410 }
1411
1412 static int featuregroup_handler(const struct aco_option *opt,
1413                 struct ast_variable *var, void *obj)
1414 {
1415         RAII_VAR(struct featuregroup_item *, item, NULL, ao2_cleanup);
1416         struct featuregroup *group = obj;
1417
1418         item = ao2_alloc(sizeof(*item), featuregroup_item_destructor);
1419         if (!item || ast_string_field_init(item, 32)) {
1420                 return -1;
1421         }
1422
1423         ast_string_field_set(item, appmap_item_name, var->name);
1424         ast_string_field_set(item, dtmf_override, var->value);
1425
1426         if (!ao2_link(group->items, item)) {
1427                 return -1;
1428         }
1429
1430         /* We wait to look up the application map item in the preapply callback */
1431
1432         return 0;
1433 }
1434
1435 static int general_handler(const struct aco_option *opt,
1436                 struct ast_variable *var, void *obj)
1437 {
1438         struct features_global_config *global = obj;
1439         struct ast_features_general_config *general = global->general;
1440
1441         return general_set(general, var->name, var->value);
1442 }
1443
1444 static int xfer_handler(const struct aco_option *opt,
1445                 struct ast_variable *var, void *obj)
1446 {
1447         struct features_global_config *global = obj;
1448         struct ast_features_xfer_config *xfer = global->xfer;
1449
1450         return xfer_set(xfer, var->name, var->value);
1451 }
1452
1453 static int pickup_handler(const struct aco_option *opt,
1454                 struct ast_variable *var, void *obj)
1455 {
1456         struct features_global_config *global = obj;
1457         struct ast_features_pickup_config *pickup = global->pickup;
1458
1459         return pickup_set(pickup, var->name, var->value);
1460 }
1461
1462 static int parking_warning = 0;
1463 static int unsupported_handler(const struct aco_option *opt,
1464                 struct ast_variable *var, void *obj)
1465 {
1466         if (!parking_warning) {
1467                 ast_log(LOG_WARNING, "Parkinglots are no longer configurable in features.conf; "
1468                         "parking is now handled by res_parking.conf\n");
1469                 parking_warning = 1;
1470         }
1471         ast_log(LOG_WARNING, "The option '%s' is no longer configurable in features.conf.\n", var->name);
1472         return 0;
1473 }
1474
1475 static int featuremap_handler(const struct aco_option *opt,
1476                 struct ast_variable *var, void *obj)
1477 {
1478         struct ast_featuremap_config *featuremap = obj;
1479
1480         return featuremap_set(featuremap, var->name, var->value);
1481 }
1482
1483 static int check_featuregroup_item(void *obj, void *arg, void *data, int flags)
1484 {
1485         struct ast_applicationmap_item *appmap_item;
1486         struct featuregroup_item *fg_item = obj;
1487         int *err = arg;
1488         struct ao2_container *applicationmap = data;
1489
1490         appmap_item = ao2_find(applicationmap, fg_item->appmap_item_name, OBJ_KEY);
1491         if (!appmap_item) {
1492                 *err = 1;
1493                 return CMP_STOP;
1494         }
1495
1496         fg_item->appmap_item = appmap_item;
1497
1498         return 0;
1499 }
1500
1501 static int check_featuregroup(void *obj, void *arg, void *data, int flags)
1502 {
1503         struct featuregroup *group = obj;
1504         int *err = arg;
1505
1506         ao2_callback_data(group->items, 0, check_featuregroup_item, arg, data);
1507
1508         if (*err) {
1509                 ast_log(LOG_WARNING, "Featuregroup %s refers to non-existent applicationmap item\n",
1510                                 group->name);
1511         }
1512
1513         return *err ? CMP_STOP : 0;
1514 }
1515
1516 static int features_pre_apply_config(void);
1517
1518 CONFIG_INFO_CORE("features", cfg_info, globals, features_config_alloc,
1519         .files = ACO_FILES(&features_conf),
1520         .pre_apply_config = features_pre_apply_config,
1521 );
1522
1523 static int features_pre_apply_config(void)
1524 {
1525         struct features_config *cfg = aco_pending_config(&cfg_info);
1526         int err = 0;
1527
1528         /* Now that the entire config has been processed, we can check that the featuregroup
1529          * items refer to actual applicationmap items.
1530          */
1531
1532         ao2_callback_data(cfg->featuregroups, 0, check_featuregroup, &err, cfg->applicationmap);
1533
1534         return err;
1535 }
1536
1537 static int feature_read(struct ast_channel *chan, const char *cmd, char *data,
1538                char *buf, size_t len)
1539 {
1540         int res;
1541         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1542         SCOPED_CHANNELLOCK(lock, chan);
1543
1544         if (!strcasecmp(data, "inherit")) {
1545                 struct ast_datastore *ds = get_feature_chan_ds(chan);
1546                 unsigned int inherit = ds ? ds->inheritance : 0;
1547
1548                 snprintf(buf, len, "%s", inherit ? "yes" : "no");
1549                 return 0;
1550         }
1551
1552         cfg = get_feature_ds(chan);
1553         if (!cfg) {
1554                 return -1;
1555         }
1556
1557         res = general_get(cfg->global->general, data, buf, len) &&
1558                 xfer_get(cfg->global->xfer, data, buf, len) &&
1559                 pickup_get(cfg->global->pickup, data, buf, len);
1560
1561         if (res) {
1562                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
1563         }
1564
1565         return res;
1566 }
1567
1568 static int feature_write(struct ast_channel *chan, const char *cmd, char *data,
1569                 const char *value)
1570 {
1571         int res;
1572         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1573         SCOPED_CHANNELLOCK(lock, chan);
1574
1575         if (!strcasecmp(data, "inherit")) {
1576                 struct ast_datastore *ds = get_feature_chan_ds(chan);
1577                 if (ds) {
1578                         ds->inheritance = ast_true(value) ? DATASTORE_INHERIT_FOREVER : 0;
1579                 }
1580                 return 0;
1581         }
1582
1583         if (!(cfg = get_feature_ds(chan))) {
1584                 return -1;
1585         }
1586
1587         res = general_set(cfg->global->general, data, value) &&
1588                 xfer_set(cfg->global->xfer, data, value) &&
1589                 pickup_set(cfg->global->pickup, data, value);
1590
1591         if (res) {
1592                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
1593         }
1594
1595         return res;
1596 }
1597
1598 static int featuremap_read(struct ast_channel *chan, const char *cmd, char *data,
1599                char *buf, size_t len)
1600 {
1601         int res;
1602         SCOPED_CHANNELLOCK(lock, chan);
1603
1604         res = ast_get_builtin_feature(chan, data, buf, len);
1605
1606         if (res) {
1607                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATUREMAP()\n", data);
1608         }
1609
1610         return res;
1611 }
1612
1613 static int featuremap_write(struct ast_channel *chan, const char *cmd, char *data,
1614                 const char *value)
1615 {
1616         int res;
1617         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1618         SCOPED_CHANNELLOCK(lock, chan);
1619
1620         if (!(cfg = get_feature_ds(chan))) {
1621                 return -1;
1622         }
1623
1624         res = featuremap_set(cfg->featuremap, data, value);
1625         if (res) {
1626                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATUREMAP()\n", data);
1627                 return -1;
1628         }
1629
1630         return 0;
1631 }
1632
1633 static struct ast_custom_function feature_function = {
1634         .name = "FEATURE",
1635         .read = feature_read,
1636         .write = feature_write
1637 };
1638
1639 static struct ast_custom_function featuremap_function = {
1640         .name = "FEATUREMAP",
1641         .read = featuremap_read,
1642         .write = featuremap_write
1643 };
1644
1645 static int load_config(void)
1646 {
1647         if (aco_info_init(&cfg_info)) {
1648                 ast_log(LOG_ERROR, "Unable to initialize configuration info for features\n");
1649                 return -1;
1650         }
1651
1652         aco_option_register_custom(&cfg_info, "featuredigittimeout", ACO_EXACT, global_options,
1653                         __stringify(DEFAULT_FEATURE_DIGIT_TIMEOUT), general_handler, 0);
1654         aco_option_register_custom(&cfg_info, "recordingfailsound", ACO_EXACT, global_options,
1655                         DEFAULT_RECORDING_FAIL_SOUND, general_handler, 0);
1656         aco_option_register_custom(&cfg_info, "courtesytone", ACO_EXACT, global_options,
1657                         DEFAULT_COURTESY_TONE, general_handler, 0);
1658
1659         aco_option_register_custom(&cfg_info, "transferdigittimeout", ACO_EXACT, global_options,
1660                         __stringify(DEFAULT_TRANSFER_DIGIT_TIMEOUT), xfer_handler, 0)
1661         aco_option_register_custom(&cfg_info, "atxfernoanswertimeout", ACO_EXACT, global_options,
1662                         __stringify(DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER), xfer_handler, 0);
1663         aco_option_register_custom(&cfg_info, "atxferdropcall", ACO_EXACT, global_options,
1664                         __stringify(DEFAULT_ATXFER_DROP_CALL), xfer_handler, 0);
1665         aco_option_register_custom(&cfg_info, "atxferloopdelay", ACO_EXACT, global_options,
1666                         __stringify(DEFAULT_ATXFER_LOOP_DELAY), xfer_handler, 0);
1667         aco_option_register_custom(&cfg_info, "atxfercallbackretries", ACO_EXACT, global_options,
1668                         __stringify(DEFAULT_ATXFER_CALLBACK_RETRIES), xfer_handler, 0);
1669         aco_option_register_custom(&cfg_info, "xfersound", ACO_EXACT, global_options,
1670                         DEFAULT_XFERSOUND, xfer_handler, 0);
1671         aco_option_register_custom(&cfg_info, "xferfailsound", ACO_EXACT, global_options,
1672                         DEFAULT_XFERFAILSOUND, xfer_handler, 0);
1673         aco_option_register_custom(&cfg_info, "atxferabort", ACO_EXACT, global_options,
1674                         DEFAULT_ATXFER_ABORT, xfer_handler, 0);
1675         aco_option_register_custom(&cfg_info, "atxfercomplete", ACO_EXACT, global_options,
1676                         DEFAULT_ATXFER_COMPLETE, xfer_handler, 0);
1677         aco_option_register_custom(&cfg_info, "atxferthreeway", ACO_EXACT, global_options,
1678                         DEFAULT_ATXFER_THREEWAY, xfer_handler, 0);
1679         aco_option_register_custom(&cfg_info, "atxferswap", ACO_EXACT, global_options,
1680                         DEFAULT_ATXFER_SWAP, xfer_handler, 0);
1681
1682         aco_option_register_custom(&cfg_info, "pickupexten", ACO_EXACT, global_options,
1683                         DEFAULT_PICKUPEXTEN, pickup_handler, 0);
1684         aco_option_register_custom(&cfg_info, "pickupsound", ACO_EXACT, global_options,
1685                         DEFAULT_PICKUPSOUND, pickup_handler, 0);
1686         aco_option_register_custom(&cfg_info, "pickupfailsound", ACO_EXACT, global_options,
1687                         DEFAULT_PICKUPFAILSOUND, pickup_handler, 0);
1688
1689         aco_option_register_custom_nodoc(&cfg_info, "context", ACO_EXACT, global_options,
1690                         "", unsupported_handler, 0);
1691         aco_option_register_custom_nodoc(&cfg_info, "parkext", ACO_EXACT, global_options,
1692                         "", unsupported_handler, 0);
1693         aco_option_register_custom_nodoc(&cfg_info, "parkext_exclusive", ACO_EXACT, global_options,
1694                         "", unsupported_handler, 0);
1695         aco_option_register_custom_nodoc(&cfg_info, "parkinghints", ACO_EXACT, global_options,
1696                         "", unsupported_handler, 0);
1697         aco_option_register_custom_nodoc(&cfg_info, "parkedmusicclass", ACO_EXACT, global_options,
1698                         "", unsupported_handler, 0);
1699         aco_option_register_custom_nodoc(&cfg_info, "parkingtime", ACO_EXACT, global_options,
1700                         "", unsupported_handler, 0);
1701         aco_option_register_custom_nodoc(&cfg_info, "parkpos", ACO_EXACT, global_options,
1702                         "", unsupported_handler, 0);
1703         aco_option_register_custom_nodoc(&cfg_info, "findslot", ACO_EXACT, global_options,
1704                         "", unsupported_handler, 0);
1705         aco_option_register_custom_nodoc(&cfg_info, "parkedcalltransfers", ACO_EXACT, global_options,
1706                         "", unsupported_handler, 0);
1707         aco_option_register_custom_nodoc(&cfg_info, "parkedcallreparking", ACO_EXACT, global_options,
1708                         "", unsupported_handler, 0);
1709         aco_option_register_custom_nodoc(&cfg_info, "parkedcallhangup", ACO_EXACT, global_options,
1710                         "", unsupported_handler, 0);
1711         aco_option_register_custom_nodoc(&cfg_info, "parkedcallrecording", ACO_EXACT, global_options,
1712                         "", unsupported_handler, 0);
1713         aco_option_register_custom_nodoc(&cfg_info, "comebackcontext", ACO_EXACT, global_options,
1714                         "", unsupported_handler, 0);
1715         aco_option_register_custom_nodoc(&cfg_info, "comebacktoorigin", ACO_EXACT, global_options,
1716                         "", unsupported_handler, 0);
1717         aco_option_register_custom_nodoc(&cfg_info, "comebackdialtime", ACO_EXACT, global_options,
1718                         "", unsupported_handler, 0);
1719         aco_option_register_custom_nodoc(&cfg_info, "parkeddynamic", ACO_EXACT, global_options,
1720                         "", unsupported_handler, 0);
1721         aco_option_register_custom_nodoc(&cfg_info, "adsipark", ACO_EXACT, global_options,
1722                         "", unsupported_handler, 0);
1723
1724         aco_option_register_custom(&cfg_info, "blindxfer", ACO_EXACT, featuremap_options,
1725                         DEFAULT_FEATUREMAP_BLINDXFER, featuremap_handler, 0);
1726         aco_option_register_custom(&cfg_info, "disconnect", ACO_EXACT, featuremap_options,
1727                         DEFAULT_FEATUREMAP_DISCONNECT, featuremap_handler, 0);
1728         aco_option_register_custom(&cfg_info, "automon", ACO_EXACT, featuremap_options,
1729                         DEFAULT_FEATUREMAP_AUTOMON, featuremap_handler, 0);
1730         aco_option_register_custom(&cfg_info, "atxfer", ACO_EXACT, featuremap_options,
1731                         DEFAULT_FEATUREMAP_ATXFER, featuremap_handler, 0);
1732         aco_option_register_custom(&cfg_info, "parkcall", ACO_EXACT, featuremap_options,
1733                         DEFAULT_FEATUREMAP_PARKCALL, featuremap_handler, 0);
1734         aco_option_register_custom(&cfg_info, "automixmon", ACO_EXACT, featuremap_options,
1735                         DEFAULT_FEATUREMAP_AUTOMIXMON, featuremap_handler, 0);
1736
1737         aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, applicationmap_options,
1738                         "", applicationmap_handler, 0);
1739
1740         aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, featuregroup_options,
1741                         "", featuregroup_handler, 0);
1742
1743         aco_option_register_custom_nodoc(&cfg_info, "^.*$", ACO_REGEX, parkinglot_options,
1744                         "", unsupported_handler, 0);
1745
1746         if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
1747                 RAII_VAR(struct features_config *, features_cfg, __features_config_alloc(0), ao2_cleanup);
1748
1749                 if (aco_set_defaults(&global_option, "general", features_cfg->global) ||
1750                         aco_set_defaults(&featuremap_option, "featuremap", features_cfg->featuremap)) {
1751                         ast_log(LOG_ERROR, "Failed to load features.conf and failed to initialize defaults.\n");
1752                         return -1;
1753                 }
1754
1755                 ast_log(LOG_NOTICE, "Could not load features config; using defaults\n");
1756                 ao2_global_obj_replace_unref(globals, features_cfg);
1757         }
1758
1759         return 0;
1760 }
1761
1762 static int print_featuregroup(void *obj, void *arg, int flags)
1763 {
1764         struct featuregroup_item *item = obj;
1765         struct ast_cli_args *a = arg;
1766
1767         ast_cli(a->fd, "===> --> %s (%s)\n", item->appmap_item_name,
1768                         S_OR(item->dtmf_override, item->appmap_item->dtmf));
1769
1770         return 0;
1771 }
1772
1773 static int print_featuregroups(void *obj, void *arg, int flags)
1774 {
1775         struct featuregroup *group = obj;
1776         struct ast_cli_args *a = arg;
1777
1778         ast_cli(a->fd, "===> Group: %s\n", group->name);
1779
1780         ao2_callback(group->items, 0, print_featuregroup, a);
1781         return 0;
1782 }
1783
1784 #define HFS_FORMAT "%-25s %-7s %-7s\n"
1785
1786 static int print_applicationmap(void *obj, void *arg, int flags)
1787 {
1788         struct ast_applicationmap_item *item = obj;
1789         struct ast_cli_args *a = arg;
1790
1791         ast_cli(a->fd, HFS_FORMAT, item->name, "no def", item->dtmf);
1792         return 0;
1793 }
1794
1795 /*!
1796  * \brief CLI command to list configured features
1797  * \param e
1798  * \param cmd
1799  * \param a
1800  *
1801  * \retval CLI_SUCCESS on success.
1802  * \retval NULL when tab completion is used.
1803  */
1804 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1805 {
1806         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1807
1808         switch (cmd) {
1809
1810         case CLI_INIT:
1811                 e->command = "features show";
1812                 e->usage =
1813                         "Usage: features show\n"
1814                         "       Lists configured features\n";
1815                 return NULL;
1816         case CLI_GENERATE:
1817                 return NULL;
1818         }
1819
1820         cfg = ao2_global_obj_ref(globals);
1821
1822         ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
1823         ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
1824
1825         ast_cli(a->fd, HFS_FORMAT, "Pickup", DEFAULT_PICKUPEXTEN, cfg->global->pickup->pickupexten);
1826         ast_cli(a->fd, HFS_FORMAT, "Blind Transfer", DEFAULT_FEATUREMAP_BLINDXFER, cfg->featuremap->blindxfer);
1827         ast_cli(a->fd, HFS_FORMAT, "Attended Transfer", DEFAULT_FEATUREMAP_ATXFER, cfg->featuremap->atxfer);
1828         ast_cli(a->fd, HFS_FORMAT, "One Touch Monitor", DEFAULT_FEATUREMAP_AUTOMON, cfg->featuremap->automon);
1829         ast_cli(a->fd, HFS_FORMAT, "Disconnect Call", DEFAULT_FEATUREMAP_DISCONNECT, cfg->featuremap->disconnect);
1830         ast_cli(a->fd, HFS_FORMAT, "Park Call", DEFAULT_FEATUREMAP_PARKCALL, cfg->featuremap->parkcall);
1831         ast_cli(a->fd, HFS_FORMAT, "One Touch MixMonitor", DEFAULT_FEATUREMAP_AUTOMIXMON, cfg->featuremap->automixmon);
1832
1833         ast_cli(a->fd, "\n");
1834         ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
1835         ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
1836         if (!cfg->applicationmap || ao2_container_count(cfg->applicationmap) == 0) {
1837                 ast_cli(a->fd, "(none)\n");
1838         } else {
1839                 ao2_callback(cfg->applicationmap, 0, print_applicationmap, a);
1840         }
1841
1842         ast_cli(a->fd, "\nFeature Groups:\n");
1843         ast_cli(a->fd, "---------------\n");
1844         if (!cfg->featuregroups || ao2_container_count(cfg->featuregroups) == 0) {
1845                 ast_cli(a->fd, "(none)\n");
1846         } else {
1847                 ao2_callback(cfg->featuregroups, 0, print_featuregroups, a);
1848         }
1849
1850         ast_cli(a->fd, "\n");
1851
1852         return CLI_SUCCESS;
1853 }
1854
1855 static struct ast_cli_entry cli_features_config[] = {
1856         AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
1857 };
1858
1859 void ast_features_config_shutdown(void)
1860 {
1861         ast_custom_function_unregister(&featuremap_function);
1862         ast_custom_function_unregister(&feature_function);
1863         ast_cli_unregister_multiple(cli_features_config, ARRAY_LEN(cli_features_config));
1864         aco_info_destroy(&cfg_info);
1865         ao2_global_obj_release(globals);
1866 }
1867
1868 int ast_features_config_reload(void)
1869 {
1870         if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
1871                 return -1;
1872         }
1873         return 0;
1874 }
1875
1876 int ast_features_config_init(void)
1877 {
1878         int res;
1879
1880         res = load_config();
1881         res |= __ast_custom_function_register(&feature_function, NULL);
1882         res |= __ast_custom_function_register(&featuremap_function, NULL);
1883         res |= ast_cli_register_multiple(cli_features_config, ARRAY_LEN(cli_features_config));
1884
1885         if (res) {
1886                 ast_features_config_shutdown();
1887         }
1888
1889         return res;
1890 }