Wed Jan 8 2020 09:49:47

Asterisk developer's documentation


features.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, Digium, Inc.
5  *
6  * Mark Spencer <markster@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 /*! \file
20  *
21  * \brief Routines implementing call features as call pickup, parking and transfer
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 419630 $")
33 
34 #include "asterisk/_private.h"
35 
36 #include <pthread.h>
37 #include <signal.h>
38 #include <sys/time.h>
39 #include <sys/signal.h>
40 #include <netinet/in.h>
41 
42 #include "asterisk/lock.h"
43 #include "asterisk/file.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/causes.h"
47 #include "asterisk/module.h"
48 #include "asterisk/translate.h"
49 #include "asterisk/app.h"
50 #include "asterisk/say.h"
51 #include "asterisk/features.h"
52 #include "asterisk/musiconhold.h"
53 #include "asterisk/config.h"
54 #include "asterisk/cli.h"
55 #include "asterisk/manager.h"
56 #include "asterisk/utils.h"
57 #include "asterisk/adsi.h"
58 #include "asterisk/devicestate.h"
59 #include "asterisk/monitor.h"
60 #include "asterisk/audiohook.h"
62 #include "asterisk/astobj2.h"
63 #include "asterisk/cel.h"
64 #include "asterisk/test.h"
65 
66 /*
67  * Party A - transferee
68  * Party B - transferer
69  * Party C - target of transfer
70  *
71  * DTMF attended transfer works within the channel bridge.
72  * Unfortunately, when either party A or B in the channel bridge
73  * hangs up, that channel is not completely hung up until the
74  * transfer completes. This is a real problem depending upon
75  * the channel technology involved.
76  *
77  * For chan_dahdi, the channel is crippled until the hangup is
78  * complete. Either the channel is not useable (analog) or the
79  * protocol disconnect messages are held up (PRI/BRI/SS7) and
80  * the media is not released.
81  *
82  * For chan_sip, a call limit of one is going to block that
83  * endpoint from any further calls until the hangup is complete.
84  *
85  * For party A this is a minor problem. The party A channel
86  * will only be in this condition while party B is dialing and
87  * when party B and C are conferring. The conversation between
88  * party B and C is expected to be a short one. Party B is
89  * either asking a question of party C or announcing party A.
90  * Also party A does not have much incentive to hangup at this
91  * point.
92  *
93  * For party B this can be a major problem during a blonde
94  * transfer. (A blonde transfer is our term for an attended
95  * transfer that is converted into a blind transfer. :)) Party
96  * B could be the operator. When party B hangs up, he assumes
97  * that he is out of the original call entirely. The party B
98  * channel will be in this condition while party C is ringing,
99  * while attempting to recall party B, and while waiting between
100  * call attempts.
101  *
102  * WARNING:
103  * The ATXFER_NULL_TECH conditional is a hack to fix the
104  * problem. It will replace the party B channel technology with
105  * a NULL channel driver. The consequences of this code is that
106  * the 'h' extension will not be able to access any channel
107  * technology specific information like SIP statistics for the
108  * call.
109  *
110  * Uncomment the ATXFER_NULL_TECH define below to replace the
111  * party B channel technology in the channel bridge to complete
112  * hanging up the channel technology.
113  */
114 //#define ATXFER_NULL_TECH 1
115 
116 /*** DOCUMENTATION
117  <application name="Bridge" language="en_US">
118  <synopsis>
119  Bridge two channels.
120  </synopsis>
121  <syntax>
122  <parameter name="channel" required="true">
123  <para>The current channel is bridged to the specified <replaceable>channel</replaceable>.</para>
124  </parameter>
125  <parameter name="options">
126  <optionlist>
127  <option name="p">
128  <para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
129  </option>
130  <option name="h">
131  <para>Allow the called party to hang up by sending the
132  <replaceable>*</replaceable> DTMF digit.</para>
133  </option>
134  <option name="H">
135  <para>Allow the calling party to hang up by pressing the
136  <replaceable>*</replaceable> DTMF digit.</para>
137  </option>
138  <option name="k">
139  <para>Allow the called party to enable parking of the call by sending
140  the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
141  </option>
142  <option name="K">
143  <para>Allow the calling party to enable parking of the call by sending
144  the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
145  </option>
146  <option name="L(x[:y][:z])">
147  <para>Limit the call to <replaceable>x</replaceable> ms. Play a warning
148  when <replaceable>y</replaceable> ms are left. Repeat the warning every
149  <replaceable>z</replaceable> ms. The following special variables can be
150  used with this option:</para>
151  <variablelist>
152  <variable name="LIMIT_PLAYAUDIO_CALLER">
153  <para>Play sounds to the caller. yes|no (default yes)</para>
154  </variable>
155  <variable name="LIMIT_PLAYAUDIO_CALLEE">
156  <para>Play sounds to the callee. yes|no</para>
157  </variable>
158  <variable name="LIMIT_TIMEOUT_FILE">
159  <para>File to play when time is up.</para>
160  </variable>
161  <variable name="LIMIT_CONNECT_FILE">
162  <para>File to play when call begins.</para>
163  </variable>
164  <variable name="LIMIT_WARNING_FILE">
165  <para>File to play as warning if <replaceable>y</replaceable> is
166  defined. The default is to say the time remaining.</para>
167  </variable>
168  </variablelist>
169  </option>
170  <option name="S(x)">
171  <para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
172  </option>
173  <option name="t">
174  <para>Allow the called party to transfer the calling party by sending the
175  DTMF sequence defined in <filename>features.conf</filename>.</para>
176  </option>
177  <option name="T">
178  <para>Allow the calling party to transfer the called party by sending the
179  DTMF sequence defined in <filename>features.conf</filename>.</para>
180  </option>
181  <option name="w">
182  <para>Allow the called party to enable recording of the call by sending
183  the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
184  </option>
185  <option name="W">
186  <para>Allow the calling party to enable recording of the call by sending
187  the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
188  </option>
189  <option name="x">
190  <para>Cause the called party to be hung up after the bridge, instead of being
191  restarted in the dialplan.</para>
192  </option>
193  </optionlist>
194  </parameter>
195  </syntax>
196  <description>
197  <para>Allows the ability to bridge two channels via the dialplan.</para>
198  <para>This application sets the following channel variable upon completion:</para>
199  <variablelist>
200  <variable name="BRIDGERESULT">
201  <para>The result of the bridge attempt as a text string.</para>
202  <value name="SUCCESS" />
203  <value name="FAILURE" />
204  <value name="LOOP" />
205  <value name="NONEXISTENT" />
206  <value name="INCOMPATIBLE" />
207  </variable>
208  </variablelist>
209  </description>
210  </application>
211  <application name="ParkedCall" language="en_US">
212  <synopsis>
213  Retrieve a parked call.
214  </synopsis>
215  <syntax>
216  <parameter name="exten">
217  <para>Parking space extension to retrieve a parked call.
218  If not provided then the first available parked call in the
219  parking lot will be retrieved.</para>
220  </parameter>
221  <parameter name="parking_lot_name">
222  <para>Specify from which parking lot to retrieve a parked call.</para>
223  <para>The parking lot used is selected in the following order:</para>
224  <para>1) parking_lot_name option</para>
225  <para>2) <variable>PARKINGLOT</variable> variable</para>
226  <para>3) <literal>CHANNEL(parkinglot)</literal> function
227  (Possibly preset by the channel driver.)</para>
228  <para>4) Default parking lot.</para>
229  </parameter>
230  </syntax>
231  <description>
232  <para>Used to retrieve a parked call from a parking lot.</para>
233  <note>
234  <para>Parking lots automatically create and manage dialplan extensions in
235  the parking lot context. You do not need to explicitly use this
236  application in your dialplan. Instead, all you should do is include the
237  parking lot context in your dialplan.</para>
238  </note>
239  </description>
240  <see-also>
241  <ref type="application">Park</ref>
242  <ref type="application">ParkAndAnnounce</ref>
243  </see-also>
244  </application>
245  <application name="Park" language="en_US">
246  <synopsis>
247  Park yourself.
248  </synopsis>
249  <syntax>
250  <parameter name="timeout">
251  <para>A custom parking timeout for this parked call. Value in milliseconds.</para>
252  </parameter>
253  <parameter name="return_context">
254  <para>The context to return the call to after it times out.</para>
255  </parameter>
256  <parameter name="return_exten">
257  <para>The extension to return the call to after it times out.</para>
258  </parameter>
259  <parameter name="return_priority">
260  <para>The priority to return the call to after it times out.</para>
261  </parameter>
262  <parameter name="options">
263  <para>A list of options for this parked call.</para>
264  <optionlist>
265  <option name="r">
266  <para>Send ringing instead of MOH to the parked call.</para>
267  </option>
268  <option name="R">
269  <para>Randomize the selection of a parking space.</para>
270  </option>
271  <option name="s">
272  <para>Silence announcement of the parking space number.</para>
273  </option>
274  </optionlist>
275  </parameter>
276  <parameter name="parking_lot_name">
277  <para>Specify in which parking lot to park a call.</para>
278  <para>The parking lot used is selected in the following order:</para>
279  <para>1) parking_lot_name option</para>
280  <para>2) <variable>PARKINGLOT</variable> variable</para>
281  <para>3) <literal>CHANNEL(parkinglot)</literal> function
282  (Possibly preset by the channel driver.)</para>
283  <para>4) Default parking lot.</para>
284  </parameter>
285  </syntax>
286  <description>
287  <para>Used to park yourself (typically in combination with a supervised
288  transfer to know the parking space).</para>
289  <para>If you set the <variable>PARKINGEXTEN</variable> variable to a
290  parking space extension in the parking lot, Park() will attempt to park the call
291  on that extension. If the extension is already is in use then execution
292  will continue at the next priority.</para>
293  <para>If the <literal>parkeddynamic</literal> option is enabled in <filename>features.conf</filename>
294  the following variables can be used to dynamically create new parking lots.</para>
295  <para>If you set the <variable>PARKINGDYNAMIC</variable> variable and this parking lot
296  exists then it will be used as a template for the newly created dynamic lot. Otherwise,
297  the default parking lot will be used.</para>
298  <para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable then the newly created dynamic
299  parking lot will use this context.</para>
300  <para>If you set the <variable>PARKINGDYNEXTEN</variable> variable then the newly created dynamic
301  parking lot will use this extension to access the parking lot.</para>
302  <para>If you set the <variable>PARKINGDYNPOS</variable> variable then the newly created dynamic parking lot
303  will use those parking postitions.</para>
304  <note>
305  <para>This application must be used as the first extension priority
306  to be recognized as a parking access extension. DTMF transfers
307  and some channel drivers need this distinction to operate properly.
308  The parking access extension in this case is treated like a dialplan
309  hint.</para>
310  </note>
311  <note>
312  <para>Parking lots automatically create and manage dialplan extensions in
313  the parking lot context. You do not need to explicitly use this
314  application in your dialplan. Instead, all you should do is include the
315  parking lot context in your dialplan.</para>
316  </note>
317  </description>
318  <see-also>
319  <ref type="application">ParkAndAnnounce</ref>
320  <ref type="application">ParkedCall</ref>
321  </see-also>
322  </application>
323  <manager name="ParkedCalls" language="en_US">
324  <synopsis>
325  List parked calls.
326  </synopsis>
327  <syntax>
328  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
329  </syntax>
330  <description>
331  <para>List parked calls.</para>
332  </description>
333  </manager>
334  <manager name="Park" language="en_US">
335  <synopsis>
336  Park a channel.
337  </synopsis>
338  <syntax>
339  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
340  <parameter name="Channel" required="true">
341  <para>Channel name to park.</para>
342  </parameter>
343  <parameter name="Channel2" required="true">
344  <para>Channel to return to if timeout.</para>
345  </parameter>
346  <parameter name="Timeout">
347  <para>Number of milliseconds to wait before callback.</para>
348  </parameter>
349  <parameter name="Parkinglot">
350  <para>Specify in which parking lot to park the channel.</para>
351  </parameter>
352  </syntax>
353  <description>
354  <para>Park a channel.</para>
355  </description>
356  </manager>
357  <manager name="Bridge" language="en_US">
358  <synopsis>
359  Bridge two channels already in the PBX.
360  </synopsis>
361  <syntax>
362  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
363  <parameter name="Channel1" required="true">
364  <para>Channel to Bridge to Channel2.</para>
365  </parameter>
366  <parameter name="Channel2" required="true">
367  <para>Channel to Bridge to Channel1.</para>
368  </parameter>
369  <parameter name="Tone">
370  <para>Play courtesy tone to Channel 2.</para>
371  <enumlist>
372  <enum name="yes" />
373  <enum name="no" />
374  </enumlist>
375  </parameter>
376  </syntax>
377  <description>
378  <para>Bridge together two channels already in the PBX.</para>
379  </description>
380  </manager>
381  ***/
382 
383 #define DEFAULT_PARK_TIME 45000 /*!< ms */
384 #define DEFAULT_PARK_EXTENSION "700"
385 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000 /*!< ms */
386 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 1000 /*!< ms */
387 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000 /*!< ms */
388 #define DEFAULT_ATXFER_DROP_CALL 0 /*!< Do not drop call. */
389 #define DEFAULT_ATXFER_LOOP_DELAY 10000 /*!< ms */
390 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
391 
392 #define AST_MAX_WATCHERS 256
393 #define MAX_DIAL_FEATURE_OPTIONS 30
394 
399  );
401 };
402 
404  AST_LIST_ENTRY(feature_group) entry;
406  AST_STRING_FIELD(gname);
407  );
409 };
410 
411 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
412 
413 typedef enum {
414  FEATURE_INTERPRET_DETECT, /* Used by ast_feature_detect */
415  FEATURE_INTERPRET_DO, /* Used by feature_interpret */
416  FEATURE_INTERPRET_CHECK, /* Used by feature_check */
418 
419 static const char *parkedcall = "ParkedCall";
420 
421 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
422 
423 /*! Parking lot access ramp dialplan usage entry. */
425  /*! Next node in the parking lot spaces dialplan list. */
427  /*! TRUE if the parking lot access extension is exclusive. */
428  unsigned int exclusive:1;
429  /*! Parking lot access extension */
430  char exten[1];
431 };
432 
433 /*! Parking lot dialplan access ramp map */
435 
436 /*! Parking lot spaces dialplan usage entry. */
438  /*! Next node in the parking lot spaces dialplan list. */
439  AST_LIST_ENTRY(parking_dp_spaces) node;
440  /*! First parking space */
441  int start;
442  /*! Last parking space */
443  int stop;
444 };
445 
446 /*! Parking lot dialplan context space map */
448 
449 /*! Parking lot context dialplan usage entry. */
451  /*! Next node in the parking lot contexts dialplan list. */
452  AST_LIST_ENTRY(parking_dp_context) node;
453  /*! Parking access extensions defined in this context. */
454  struct parking_dp_ramp_map access_extens;
455  /*! Parking spaces defined in this context. */
456  struct parking_dp_space_map spaces;
457  /*! Parking hints defined in this context. */
458  struct parking_dp_space_map hints;
459  /*! Parking lot context name */
460  char context[1];
461 };
462 
463 /*! Parking lot dialplan usage map. */
465 
466 /*!
467  * \brief Description of one parked call, added to a list while active, then removed.
468  * The list belongs to a parkinglot.
469  */
470 struct parkeduser {
471  struct ast_channel *chan; /*!< Parked channel */
472  struct timeval start; /*!< Time the park started */
473  int parkingnum; /*!< Parking lot space used */
474  char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
475  char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
476  char exten[AST_MAX_EXTENSION];
477  int priority;
478  int parkingtime; /*!< Maximum length in parking lot before return */
479  /*! Method to entertain the caller when parked: AST_CONTROL_RINGING, AST_CONTROL_HOLD, or 0(none) */
480  enum ast_control_frame_type hold_method;
481  unsigned int notquiteyet:1;
482  unsigned int options_specified:1;
483  char peername[AST_CHANNEL_NAME];
484  unsigned char moh_trys;
485  /*! Parking lot this entry belongs to. Holds a parking lot reference. */
487  AST_LIST_ENTRY(parkeduser) list;
488 };
489 
490 /*! Parking lot configuration options. */
492  /*! Music class used for parking */
494  /*! Extension to park calls in this parking lot. */
495  char parkext[AST_MAX_EXTENSION];
496  /*! Context for which parking is made accessible */
497  char parking_con[AST_MAX_EXTENSION];
498  /*! First available extension for parking */
500  /*! Last available extension for parking */
502  /*! Default parking time in ms. */
504  /*!
505  * \brief Enable DTMF based transfers on bridge when picking up parked calls.
506  *
507  * \details
508  * none(0)
509  * AST_FEATURE_FLAG_BYCALLEE
510  * AST_FEATURE_FLAG_BYCALLER
511  * AST_FEATURE_FLAG_BYBOTH
512  */
514  /*!
515  * \brief Enable DTMF based parking on bridge when picking up parked calls.
516  *
517  * \details
518  * none(0)
519  * AST_FEATURE_FLAG_BYCALLEE
520  * AST_FEATURE_FLAG_BYCALLER
521  * AST_FEATURE_FLAG_BYBOTH
522  */
524  /*!
525  * \brief Enable DTMF based hangup on a bridge when pickup up parked calls.
526  *
527  * \details
528  * none(0)
529  * AST_FEATURE_FLAG_BYCALLEE
530  * AST_FEATURE_FLAG_BYCALLER
531  * AST_FEATURE_FLAG_BYBOTH
532  */
534  /*!
535  * \brief Enable DTMF based recording on a bridge when picking up parked calls.
536  *
537  * \details
538  * none(0)
539  * AST_FEATURE_FLAG_BYCALLEE
540  * AST_FEATURE_FLAG_BYCALLER
541  * AST_FEATURE_FLAG_BYBOTH
542  */
544 
545  /*! TRUE if findslot is set to next */
546  unsigned int parkfindnext:1;
547  /*! TRUE if the parking lot is exclusively accessed by parkext */
548  unsigned int parkext_exclusive:1;
549  /*! Add parking hints automatically */
550  unsigned int parkaddhints:1;
551  /*! TRUE if configuration is invalid and the parking lot should not be used. */
552  unsigned int is_invalid:1;
553 };
554 
555 /*! \brief Structure for parking lots which are put in a container. */
557  /*! Name of the parking lot. */
559  /*! Parking lot user configuration. */
560  struct parkinglot_cfg cfg;
561 
562  /*! Parking space to start next park search. */
564 
565  /*! That which bears the_mark shall be deleted if parking lot empty! (Used during reloads.) */
566  unsigned int the_mark:1;
567  /*! TRUE if the parking lot is disabled. */
568  unsigned int disabled:1;
569 
570  /*! List of active parkings in this parkinglot */
571  AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings;
572 };
573 
574 /*! \brief The configured parking lots container. Always at least one - the default parking lot */
575 static struct ao2_container *parkinglots;
576 
577 /*!
578  * \brief Default parking lot.
579  * \note Holds a parkinglot reference.
580  * \note Will not be NULL while running.
581  */
583 
584 /*! Force a config reload to reload regardless of config file timestamp. */
585 static int force_reload_load;
586 
587 static int parkedplay = 0; /*!< Who to play courtesytone to when someone picks up a parked call. */
588 static int parkeddynamic = 0; /*!< Enable creation of parkinglots dynamically */
589 static char courtesytone[256]; /*!< Courtesy tone used to pickup parked calls and on-touch-record */
590 static char xfersound[256]; /*!< Call transfer sound */
591 static char xferfailsound[256]; /*!< Call transfer failure sound */
592 static char pickupsound[256]; /*!< Pickup sound */
593 static char pickupfailsound[256]; /*!< Pickup failure sound */
594 
595 static char parkingretcidname[256]; /*!< Callerid name of returned parked call */
596 static char parkingretdahdiring[3]; /*!< Distinctive ring if chantech = DAHDI */
597 static char parkingretalertinfo[256]; /*!< Distinctive ring if chantech = SIP (adds a SIP AlertInfo header) */
598 
599 /*!
600  * \brief Context for parking dialback to parker.
601  * \note The need for the context is a KLUDGE.
602  *
603  * \todo Might be able to eliminate the parking_con_dial context
604  * kludge by running app_dial directly in its own thread to
605  * simulate a PBX.
606  */
607 static char parking_con_dial[] = "park-dial";
608 
609 /*! Ensure that features.conf reloads on one thread at a time. */
611 
612 static int adsipark;
613 
616 static int comebacktoorigin = 1;
617 
619 static unsigned int atxferdropcall;
620 static unsigned int atxferloopdelay;
621 static unsigned int atxfercallbackretries;
622 
623 static char *registrar = "features"; /*!< Registrar for operations */
624 
625 /*! PARK_APP_NAME application arguments */
627  AST_APP_ARG(timeout); /*!< Time in ms to remain in the parking lot. */
628  AST_APP_ARG(return_con); /*!< Context to return parked call if timeout. */
629  AST_APP_ARG(return_ext); /*!< Exten to return parked call if timeout. */
630  AST_APP_ARG(return_pri); /*!< Priority to return parked call if timeout. */
631  AST_APP_ARG(options); /*!< Parking option flags. */
632  AST_APP_ARG(pl_name); /*!< Parking lot name to use if present. */
633  AST_APP_ARG(dummy); /*!< Place to put any remaining args string. */
634  );
635 
636 /* module and CLI command definitions */
637 static const char *parkcall = "Park";
638 
639 static struct ast_app *monitor_app = NULL;
640 static int monitor_ok = 1;
641 
642 static struct ast_app *mixmonitor_app = NULL;
643 static int mixmonitor_ok = 1;
644 
645 static struct ast_app *stopmixmonitor_app = NULL;
646 static int stopmixmonitor_ok = 1;
647 
648 static pthread_t parking_thread;
650  /*! Channel's feature flags. */
651  struct ast_flags my_features;
652  /*! Bridge peer's feature flags. */
653  struct ast_flags peer_features;
654 };
655 
656 #if defined(ATXFER_NULL_TECH)
657 /*!
658  * \internal
659  * \brief Set the channel technology to the kill technology.
660  *
661  * \param chan Channel to change technology.
662  *
663  * \return Nothing
664  */
665 static void set_kill_chan_tech(struct ast_channel *chan)
666 {
667  int idx;
668 
669  ast_channel_lock(chan);
670 
671  /* Hangup the channel's physical side */
672  if (chan->tech->hangup) {
673  chan->tech->hangup(chan);
674  }
675  if (chan->tech_pvt) {
676  ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n",
677  chan->name);
678  ast_free(chan->tech_pvt);
679  chan->tech_pvt = NULL;
680  }
681 
682  /* Install the kill technology and wake up anyone waiting on it. */
683  chan->tech = &ast_kill_tech;
684  for (idx = 0; idx < AST_MAX_FDS; ++idx) {
685  switch (idx) {
686  case AST_ALERT_FD:
687  case AST_TIMING_FD:
688  case AST_GENERATOR_FD:
689  /* Don't clear these fd's. */
690  break;
691  default:
692  ast_channel_set_fd(chan, idx, -1);
693  break;
694  }
695  }
697 
698  ast_channel_unlock(chan);
699 }
700 #endif /* defined(ATXFER_NULL_TECH) */
701 
702 #if defined(ATXFER_NULL_TECH)
703 /*!
704  * \internal
705  * \brief Set the channel name to something unique.
706  *
707  * \param chan Channel to change name.
708  *
709  * \return Nothing
710  */
711 static void set_new_chan_name(struct ast_channel *chan)
712 {
713  static int seq_num_last;
714  int seq_num;
715  int len;
716  char *chan_name;
717  char dummy[1];
718 
719  /* Create the new channel name string. */
720  ast_channel_lock(chan);
721  seq_num = ast_atomic_fetchadd_int(&seq_num_last, +1);
722  len = snprintf(dummy, sizeof(dummy), "%s<XFER_%x>", chan->name, seq_num) + 1;
723  chan_name = ast_alloca(len);
724  snprintf(chan_name, len, "%s<XFER_%x>", chan->name, seq_num);
725  ast_channel_unlock(chan);
726 
727  ast_change_name(chan, chan_name);
728 }
729 #endif /* defined(ATXFER_NULL_TECH) */
730 
731 static void *dial_features_duplicate(void *data)
732 {
733  struct ast_dial_features *df = data, *df_copy;
734 
735  if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
736  return NULL;
737  }
738 
739  memcpy(df_copy, df, sizeof(*df));
740 
741  return df_copy;
742 }
743 
744 static void dial_features_destroy(void *data)
745 {
746  struct ast_dial_features *df = data;
747  if (df) {
748  ast_free(df);
749  }
750 }
751 
752 static const struct ast_datastore_info dial_features_info = {
753  .type = "dial-features",
754  .destroy = dial_features_destroy,
755  .duplicate = dial_features_duplicate,
756 };
757 
758 /*!
759  * \internal
760  * \brief Set the features datastore if it doesn't exist.
761  *
762  * \param chan Channel to add features datastore
763  * \param my_features The channel's feature flags
764  * \param peer_features The channel's bridge peer feature flags
765  *
766  * \retval TRUE if features datastore already existed.
767  */
768 static int add_features_datastore(struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
769 {
770  struct ast_datastore *datastore;
771  struct ast_dial_features *dialfeatures;
772 
773  ast_channel_lock(chan);
774  datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL);
775  ast_channel_unlock(chan);
776  if (datastore) {
777  /* Already exists. */
778  return 1;
779  }
780 
781  /* Create a new datastore with specified feature flags. */
782  datastore = ast_datastore_alloc(&dial_features_info, NULL);
783  if (!datastore) {
784  ast_log(LOG_WARNING, "Unable to create channel features datastore.\n");
785  return 0;
786  }
787  dialfeatures = ast_calloc(1, sizeof(*dialfeatures));
788  if (!dialfeatures) {
789  ast_log(LOG_WARNING, "Unable to allocate memory for feature flags.\n");
790  ast_datastore_free(datastore);
791  return 0;
792  }
793  ast_copy_flags(&dialfeatures->my_features, my_features, AST_FLAGS_ALL);
794  ast_copy_flags(&dialfeatures->peer_features, peer_features, AST_FLAGS_ALL);
796  datastore->data = dialfeatures;
797  ast_channel_lock(chan);
798  ast_channel_datastore_add(chan, datastore);
799  ast_channel_unlock(chan);
800  return 0;
801 }
802 
803 /* Forward declarations */
804 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
805 static void parkinglot_unref(struct ast_parkinglot *parkinglot);
806 static struct ast_parkinglot *find_parkinglot(const char *name);
807 static struct ast_parkinglot *create_parkinglot(const char *name);
808 static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
809 static int parkinglot_activate(struct ast_parkinglot *parkinglot);
810 static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile);
811 
812 /*!
813  * \internal
814  * \brief Get the parking extension if it exists.
815  *
816  * \param exten_str Parking extension to see if exists.
817  * \param chan Channel to autoservice while looking for exten. (Could be NULL)
818  * \param context Parking context to look in for exten.
819  *
820  * \retval exten on success.
821  * \retval NULL on error or exten does not exist.
822  */
823 static struct ast_exten *get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
824 {
825  struct ast_exten *exten;
826  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
827  const char *app_at_exten;
828 
829  ast_debug(4, "Checking if %s@%s is a parking exten\n", exten_str, context);
830  exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL,
831  E_MATCH);
832  if (!exten) {
833  return NULL;
834  }
835 
836  app_at_exten = ast_get_extension_app(exten);
837  if (!app_at_exten || strcasecmp(parkcall, app_at_exten)) {
838  return NULL;
839  }
840 
841  return exten;
842 }
843 
844 int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
845 {
846  return get_parking_exten(exten_str, chan, context) ? 1 : 0;
847 }
848 
849 const char *ast_pickup_ext(void)
850 {
851  return pickup_ext;
852 }
853 
855 {
856  struct ast_bridge_config bconfig;
857  struct ast_channel *chan;
858  struct ast_channel *peer;
859  unsigned int return_to_pbx:1;
860 };
861 
862 static int parkinglot_hash_cb(const void *obj, const int flags)
863 {
864  const struct ast_parkinglot *parkinglot = obj;
865 
866  return ast_str_case_hash(parkinglot->name);
867 }
868 
869 static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
870 {
871  struct ast_parkinglot *parkinglot = obj;
872  struct ast_parkinglot *parkinglot2 = arg;
873 
874  return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
875 }
876 
877 /*!
878  * \brief store context, extension and priority
879  * \param chan, context, ext, pri
880  */
881 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
882 {
883  ast_copy_string(chan->context, context, sizeof(chan->context));
884  ast_copy_string(chan->exten, ext, sizeof(chan->exten));
885  chan->priority = pri;
886 }
887 
888 /*!
889  * \brief Check goto on transfer
890  * \param chan
891  *
892  * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
893  * When found make sure the types are compatible. Check if channel is valid
894  * if so start the new channel else hangup the call.
895  */
896 static void check_goto_on_transfer(struct ast_channel *chan)
897 {
898  struct ast_channel *xferchan;
899  const char *val;
900  char *goto_on_transfer;
901  char *x;
902 
903  ast_channel_lock(chan);
904  val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
905  if (ast_strlen_zero(val)) {
906  ast_channel_unlock(chan);
907  return;
908  }
909  goto_on_transfer = ast_strdupa(val);
910  ast_channel_unlock(chan);
911 
912  ast_debug(1, "Attempting GOTO_ON_BLINDXFR=%s for %s.\n", val, chan->name);
913 
914  xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", chan->linkedid, 0,
915  "%s", chan->name);
916  if (!xferchan) {
917  return;
918  }
919 
920  /* Make formats okay */
921  xferchan->readformat = chan->readformat;
922  xferchan->writeformat = chan->writeformat;
923 
924  if (ast_channel_masquerade(xferchan, chan)) {
925  /* Failed to setup masquerade. */
926  ast_hangup(xferchan);
927  return;
928  }
929 
930  for (x = goto_on_transfer; *x; ++x) {
931  if (*x == '^') {
932  *x = ',';
933  }
934  }
935  ast_parseable_goto(xferchan, goto_on_transfer);
936  xferchan->_state = AST_STATE_UP;
937  ast_clear_flag(xferchan, AST_FLAGS_ALL);
939 
940  ast_do_masquerade(xferchan);
941  if (ast_pbx_start(xferchan)) {
942  /* Failed to start PBX. */
943  ast_hangup(xferchan);
944  }
945 }
946 
948  const char *caller_name, struct ast_channel *requestor,
949  struct ast_channel *transferee, const char *type, format_t format, void *data,
950  int timeout, int *outstate, const char *language);
951 
953  .type = "Channel appdata datastore",
954  .destroy = ast_free_ptr,
955 };
956 
957 static int set_chan_app_data(struct ast_channel *chan, const char *src_app_data)
958 {
959  struct ast_datastore *datastore;
960  char *dst_app_data;
961 
963  if (!datastore) {
964  return -1;
965  }
966 
967  dst_app_data = ast_malloc(strlen(src_app_data) + 1);
968  if (!dst_app_data) {
969  ast_datastore_free(datastore);
970  return -1;
971  }
972 
973  chan->data = strcpy(dst_app_data, src_app_data);
974  datastore->data = dst_app_data;
975  ast_channel_datastore_add(chan, datastore);
976  return 0;
977 }
978 
979 /*!
980  * \brief bridge the call
981  * \param data thread bridge.
982  *
983  * Set Last Data for respective channels, reset cdr for channels
984  * bridge call, check if we're going back to dialplan
985  * if not hangup both legs of the call
986  */
987 static void *bridge_call_thread(void *data)
988 {
989  struct ast_bridge_thread_obj *tobj = data;
990 
991  tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
992  if (set_chan_app_data(tobj->chan, tobj->peer->name)) {
993  tobj->chan->data = "(Empty)";
994  }
995  tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
996  if (set_chan_app_data(tobj->peer, tobj->chan->name)) {
997  tobj->peer->data = "(Empty)";
998  }
999 
1000  ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
1001 
1002  if (tobj->return_to_pbx) {
1003  if (!ast_check_hangup(tobj->peer)) {
1004  ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
1005  if (ast_pbx_start(tobj->peer)) {
1006  ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
1007  ast_hangup(tobj->peer);
1008  }
1009  } else {
1010  ast_hangup(tobj->peer);
1011  }
1012  if (!ast_check_hangup(tobj->chan)) {
1013  ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
1014  if (ast_pbx_start(tobj->chan)) {
1015  ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
1016  ast_hangup(tobj->chan);
1017  }
1018  } else {
1019  ast_hangup(tobj->chan);
1020  }
1021  } else {
1022  ast_hangup(tobj->chan);
1023  ast_hangup(tobj->peer);
1024  }
1025 
1026  ast_free(tobj);
1027 
1028  return NULL;
1029 }
1030 
1031 /*!
1032  * \brief create thread for the parked call
1033  * \param data
1034  *
1035  * Create thread and attributes, call bridge_call_thread
1036  */
1038 {
1039  pthread_t thread;
1040  pthread_attr_t attr;
1041  struct sched_param sched;
1042 
1043  pthread_attr_init(&attr);
1044  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1045  if (ast_pthread_create(&thread, &attr, bridge_call_thread, data)) {
1046  ast_hangup(data->chan);
1047  ast_hangup(data->peer);
1048  ast_log(LOG_ERROR, "Failed to create bridge_call_thread.\n");
1049  }
1050  pthread_attr_destroy(&attr);
1051  memset(&sched, 0, sizeof(sched));
1052  pthread_setschedparam(thread, SCHED_RR, &sched);
1053 }
1054 
1055 /*!
1056  * \brief Announce call parking by ADSI
1057  * \param chan .
1058  * \param parkingexten .
1059  * Create message to show for ADSI, display message.
1060  * \retval 0 on success.
1061  * \retval -1 on failure.
1062  */
1063 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
1064 {
1065  int res;
1066  int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
1067  char tmp[256];
1068  char *message[5] = {NULL, NULL, NULL, NULL, NULL};
1069 
1070  snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
1071  message[0] = tmp;
1072  res = ast_adsi_load_session(chan, NULL, 0, 1);
1073  if (res == -1)
1074  return res;
1075  return ast_adsi_print(chan, message, justify, 1);
1076 }
1077 
1078 /*!
1079  * \brief Find parking lot name from channel
1080  * \note Channel needs to be locked while the returned string is in use.
1081  */
1082 static const char *findparkinglotname(struct ast_channel *chan)
1083 {
1084  const char *name;
1085 
1086  /* The channel variable overrides everything */
1087  name = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
1088  if (!name && !ast_strlen_zero(chan->parkinglot)) {
1089  /* Use the channel's parking lot. */
1090  name = chan->parkinglot;
1091  }
1092  return name;
1093 }
1094 
1095 /*! \brief Notify metermaids that we've changed an extension */
1096 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
1097 {
1098  ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
1099  exten, context, ast_devstate2str(state));
1100 
1101  ast_devstate_changed(state, AST_DEVSTATE_CACHABLE, "park:%s@%s", exten, context);
1102 }
1103 
1104 /*! \brief metermaids callback from devicestate.c */
1105 static enum ast_device_state metermaidstate(const char *data)
1106 {
1107  char *context;
1108  char *exten;
1109 
1110  context = ast_strdupa(data);
1111 
1112  exten = strsep(&context, "@");
1113  if (!context)
1114  return AST_DEVICE_INVALID;
1115 
1116  ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
1117 
1118  if (!ast_exists_extension(NULL, context, exten, 1, NULL))
1119  return AST_DEVICE_NOT_INUSE;
1120 
1121  return AST_DEVICE_INUSE;
1122 }
1123 
1124 /*! Options to pass to park_call_full */
1126  /*! Provide ringing to the parked caller instead of music on hold */
1128  /*! Randomly choose a parking spot for the caller instead of choosing
1129  * the first one that is available. */
1131  /*! Do not announce the parking number */
1133 };
1134 
1135 /*! Optional additional parking options when parking a call. */
1137  /*! How long to wait in the parking lot before the call gets sent back
1138  * to the specified return extension (or a best guess at where it came
1139  * from if not explicitly specified). */
1140  int timeout;
1141  /*! An output parameter to store the parking space where the parked caller
1142  * was placed. */
1143  int *extout;
1144  const char *orig_chan_name;
1145  const char *return_con;
1146  const char *return_ext;
1148  uint32_t flags;
1149  /*! Parked user that has already obtained a parking space */
1150  struct parkeduser *pu;
1151  /*! \brief Parkinglot to be parked in */
1153 };
1154 
1155 /*!
1156  * \internal
1157  * \brief Create a dynamic parking lot.
1158  *
1159  * \param name Dynamic parking lot name to create.
1160  * \param chan Channel to get dynamic parking lot parameters.
1161  *
1162  * \retval parkinglot on success.
1163  * \retval NULL on error.
1164  */
1165 static struct ast_parkinglot *create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
1166 {
1167  const char *dyn_context;
1168  const char *dyn_exten;
1169  const char *dyn_range;
1170  const char *template_name;
1171  struct ast_parkinglot *template_parkinglot = NULL;
1172  struct ast_parkinglot *parkinglot;
1173  int dyn_start;
1174  int dyn_end;
1175 
1176  ast_channel_lock(chan);
1177  template_name = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
1178  dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
1179  dyn_exten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNEXTEN"), ""));
1180  dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
1181  ast_channel_unlock(chan);
1182 
1183  if (!ast_strlen_zero(template_name)) {
1184  template_parkinglot = find_parkinglot(template_name);
1185  if (!template_parkinglot) {
1186  ast_debug(1, "PARKINGDYNAMIC lot %s does not exist.\n",
1187  template_name);
1188  } else if (template_parkinglot->cfg.is_invalid) {
1189  ast_debug(1, "PARKINGDYNAMIC lot %s has invalid config.\n",
1190  template_name);
1191  parkinglot_unref(template_parkinglot);
1192  template_parkinglot = NULL;
1193  }
1194  }
1195  if (!template_parkinglot) {
1196  template_parkinglot = parkinglot_addref(default_parkinglot);
1197  ast_debug(1, "Using default parking lot for template\n");
1198  }
1199 
1200  parkinglot = copy_parkinglot(name, template_parkinglot);
1201  if (!parkinglot) {
1202  ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
1203  } else {
1204  /* Configure the dynamic parking lot. */
1205  if (!ast_strlen_zero(dyn_context)) {
1206  ast_copy_string(parkinglot->cfg.parking_con, dyn_context,
1207  sizeof(parkinglot->cfg.parking_con));
1208  }
1209  if (!ast_strlen_zero(dyn_exten)) {
1210  ast_copy_string(parkinglot->cfg.parkext, dyn_exten,
1211  sizeof(parkinglot->cfg.parkext));
1212  }
1213  if (!ast_strlen_zero(dyn_range)) {
1214  if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
1216  "Format for parking positions is a-b, where a and b are numbers\n");
1217  } else if (dyn_end < dyn_start || dyn_start <= 0 || dyn_end <= 0) {
1219  "Format for parking positions is a-b, where a <= b\n");
1220  } else {
1221  parkinglot->cfg.parking_start = dyn_start;
1222  parkinglot->cfg.parking_stop = dyn_end;
1223  }
1224  }
1225 
1226  /*
1227  * Sanity check for dynamic parking lot configuration.
1228  *
1229  * XXX It may be desirable to instead check if the dynamic
1230  * parking lot overlaps any existing lots like what is done for
1231  * a reload.
1232  */
1233  if (!strcmp(parkinglot->cfg.parking_con, template_parkinglot->cfg.parking_con)) {
1234  if (!strcmp(parkinglot->cfg.parkext, template_parkinglot->cfg.parkext)
1235  && parkinglot->cfg.parkext_exclusive) {
1237  "Parking lot '%s' conflicts with template parking lot '%s'!\n"
1238  "Change either PARKINGDYNCONTEXT or PARKINGDYNEXTEN.\n",
1239  parkinglot->name, template_parkinglot->name);
1240  }
1241  if ((template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_start
1242  && parkinglot->cfg.parking_start <= template_parkinglot->cfg.parking_stop)
1243  || (template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_stop
1244  && parkinglot->cfg.parking_stop <= template_parkinglot->cfg.parking_stop)
1245  || (parkinglot->cfg.parking_start < template_parkinglot->cfg.parking_start
1246  && template_parkinglot->cfg.parking_stop < parkinglot->cfg.parking_stop)) {
1248  "Parking lot '%s' parking spaces overlap template parking lot '%s'!\n"
1249  "Change PARKINGDYNPOS.\n",
1250  parkinglot->name, template_parkinglot->name);
1251  }
1252  }
1253 
1254  parkinglot_activate(parkinglot);
1255  ao2_link(parkinglots, parkinglot);
1256  }
1257  parkinglot_unref(template_parkinglot);
1258 
1259  return parkinglot;
1260 }
1261 
1262 /*!
1263  * \internal
1264  * \brief Abort parking a call that has not completed parking yet.
1265  *
1266  * \param pu Parked user item to clean up.
1267  *
1268  * \note The parking lot parkings list is locked on entry.
1269  *
1270  * \return Nothing
1271  */
1272 static void park_space_abort(struct parkeduser *pu)
1273 {
1274  struct ast_parkinglot *parkinglot;
1275 
1276  parkinglot = pu->parkinglot;
1277 
1278  /* Put back the parking space just allocated. */
1279  --parkinglot->next_parking_space;
1280 
1281  AST_LIST_REMOVE(&parkinglot->parkings, pu, list);
1282 
1283  AST_LIST_UNLOCK(&parkinglot->parkings);
1284  parkinglot_unref(parkinglot);
1285  ast_free(pu);
1286 }
1287 
1288 /*!
1289  * \internal
1290  * \brief Reserve a parking space in a parking lot for a call being parked.
1291  *
1292  * \param park_me Channel being parked.
1293  * \param parker Channel parking the call.
1294  * \param args Optional additional parking options when parking a call.
1295  *
1296  * \return Parked call descriptor or NULL if failed.
1297  * \note The parking lot list is locked if successful.
1298  */
1299 static struct parkeduser *park_space_reserve(struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
1300 {
1301  struct parkeduser *pu;
1302  int i;
1303  int parking_space = -1;
1304  const char *parkinglotname;
1305  const char *parkingexten;
1306  struct parkeduser *cur;
1307  struct ast_parkinglot *parkinglot = NULL;
1308 
1309  if (args->parkinglot) {
1310  parkinglot = parkinglot_addref(args->parkinglot);
1311  parkinglotname = parkinglot->name;
1312  } else {
1313  if (parker) {
1314  parkinglotname = findparkinglotname(parker);
1315  } else { /* parker was NULL, check park_me (ParkAndAnnounce / res_agi) */
1316  parkinglotname = findparkinglotname(park_me);
1317  }
1318  if (!ast_strlen_zero(parkinglotname)) {
1319  parkinglot = find_parkinglot(parkinglotname);
1320  } else {
1321  /* Parking lot is not specified, so use the default parking lot. */
1322  ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
1323  parkinglot = parkinglot_addref(default_parkinglot);
1324  }
1325  }
1326 
1327  /* Dynamically create parkinglot */
1328  if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
1329  parkinglot = create_dynamic_parkinglot(parkinglotname, park_me);
1330  }
1331 
1332  if (!parkinglot) {
1333  ast_log(LOG_WARNING, "Parking lot not available to park %s.\n", park_me->name);
1334  return NULL;
1335  }
1336 
1337  ast_debug(1, "Parking lot: %s\n", parkinglot->name);
1338  if (parkinglot->disabled || parkinglot->cfg.is_invalid) {
1339  ast_log(LOG_WARNING, "Parking lot %s is not in a useable state.\n",
1340  parkinglot->name);
1341  parkinglot_unref(parkinglot);
1342  return NULL;
1343  }
1344 
1345  /* Allocate memory for parking data */
1346  if (!(pu = ast_calloc(1, sizeof(*pu)))) {
1347  parkinglot_unref(parkinglot);
1348  return NULL;
1349  }
1350 
1351  /* Lock parking list */
1352  AST_LIST_LOCK(&parkinglot->parkings);
1353 
1354  /* Check for channel variable PARKINGEXTEN */
1355  parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(park_me, "PARKINGEXTEN"), ""));
1356  if (!ast_strlen_zero(parkingexten)) {
1357  /*!
1358  * \note The API forces us to specify a numeric parking slot, even
1359  * though the architecture would tend to support non-numeric extensions
1360  * (as are possible with SIP, for example). Hence, we enforce that
1361  * limitation here. If extout was not numeric, we could permit
1362  * arbitrary non-numeric extensions.
1363  */
1364  if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space <= 0) {
1365  ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n",
1366  parkingexten);
1367  AST_LIST_UNLOCK(&parkinglot->parkings);
1368  parkinglot_unref(parkinglot);
1369  ast_free(pu);
1370  return NULL;
1371  }
1372 
1373  if (parking_space < parkinglot->cfg.parking_start
1374  || parkinglot->cfg.parking_stop < parking_space) {
1375  /*
1376  * Cannot allow park because parking lots are not setup for
1377  * spaces outside of the lot. (Things like dialplan hints don't
1378  * exist for outside lot space.)
1379  */
1380  ast_log(LOG_WARNING, "PARKINGEXTEN=%d is not in %s (%d-%d).\n",
1381  parking_space, parkinglot->name, parkinglot->cfg.parking_start,
1382  parkinglot->cfg.parking_stop);
1383  AST_LIST_UNLOCK(&parkinglot->parkings);
1384  parkinglot_unref(parkinglot);
1385  ast_free(pu);
1386  return NULL;
1387  }
1388 
1389  /* Check if requested parking space is in use. */
1390  AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1391  if (cur->parkingnum == parking_space) {
1392  ast_log(LOG_WARNING, "PARKINGEXTEN=%d is already in use in %s\n",
1393  parking_space, parkinglot->name);
1394  AST_LIST_UNLOCK(&parkinglot->parkings);
1395  parkinglot_unref(parkinglot);
1396  ast_free(pu);
1397  return NULL;
1398  }
1399  }
1400  } else {
1401  /* PARKINGEXTEN is empty, so find a usable extension in the lot to park the call */
1402  int start; /* The first slot we look in the parkinglot. It can be randomized. */
1403  int start_checked = 0; /* flag raised once the first slot is checked */
1404 
1405  /* If using randomize mode, set start to random position on parking range */
1407  start = ast_random() % (parkinglot->cfg.parking_stop - parkinglot->cfg.parking_start + 1);
1408  start += parkinglot->cfg.parking_start;
1409  } else if (parkinglot->cfg.parkfindnext
1410  && parkinglot->cfg.parking_start <= parkinglot->next_parking_space
1411  && parkinglot->next_parking_space <= parkinglot->cfg.parking_stop) {
1412  /* Start looking with the next parking space in the lot. */
1413  start = parkinglot->next_parking_space;
1414  } else {
1415  /* Otherwise, just set it to the start position. */
1416  start = parkinglot->cfg.parking_start;
1417  }
1418 
1419  /* free parking extension linear search: O(n^2) */
1420  for (i = start; ; i++) {
1421  /* If we are past the end, wrap around to the first parking slot*/
1422  if (i == parkinglot->cfg.parking_stop + 1) {
1423  i = parkinglot->cfg.parking_start;
1424  }
1425 
1426  if (i == start) {
1427  /* At this point, if start_checked, we've exhausted all the possible slots. */
1428  if (start_checked) {
1429  break;
1430  } else {
1431  start_checked = 1;
1432  }
1433  }
1434 
1435  /* Search the list of parked calls already in use for i. If we find it, it's in use. */
1436  AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1437  if (cur->parkingnum == i) {
1438  break;
1439  }
1440  }
1441  if (!cur) {
1442  /* We found a parking space. */
1443  parking_space = i;
1444  break;
1445  }
1446  }
1447  if (parking_space == -1) {
1448  /* We did not find a parking space. Lot is full. */
1449  ast_log(LOG_WARNING, "No more parking spaces in %s\n", parkinglot->name);
1450  AST_LIST_UNLOCK(&parkinglot->parkings);
1451  parkinglot_unref(parkinglot);
1452  ast_free(pu);
1453  return NULL;
1454  }
1455  }
1456 
1457  /* Prepare for next parking space search. */
1458  parkinglot->next_parking_space = parking_space + 1;
1459 
1460  snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
1461  pu->notquiteyet = 1;
1462  pu->parkingnum = parking_space;
1463  pu->parkinglot = parkinglot;
1464  AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
1465 
1466  return pu;
1467 }
1468 
1469 /* Park a call */
1470 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
1471 {
1472  struct parkeduser *pu = args->pu;
1473  const char *event_from; /*!< Channel name that is parking the call. */
1474  char app_data[AST_MAX_EXTENSION + AST_MAX_CONTEXT];
1475 
1476  if (pu == NULL) {
1477  args->pu = pu = park_space_reserve(chan, peer, args);
1478  if (pu == NULL) {
1479  return -1;
1480  }
1481  }
1482 
1483  chan->appl = "Parked Call";
1484  chan->data = NULL;
1485 
1486  pu->chan = chan;
1487 
1488  /* Put the parked channel on hold if we have two different channels */
1489  if (chan != peer) {
1490  if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
1493  } else {
1496  S_OR(pu->parkinglot->cfg.mohclass, NULL),
1497  !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
1498  }
1499  }
1500 
1501  pu->start = ast_tvnow();
1502  pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->cfg.parkingtime;
1503  if (args->extout)
1504  *(args->extout) = pu->parkingnum;
1505 
1506  if (peer) {
1507  event_from = S_OR(args->orig_chan_name, peer->name);
1508 
1509  /*
1510  * This is so ugly that it hurts, but implementing
1511  * get_base_channel() on local channels could have ugly side
1512  * effects. We could have
1513  * transferer<->local,1<->local,2<->parking and we need the
1514  * callback name to be that of transferer. Since local,1/2 have
1515  * the same name we can be tricky and just grab the bridged
1516  * channel from the other side of the local.
1517  */
1518  if (!strcasecmp(peer->tech->type, "Local")) {
1519  struct ast_channel *tmpchan, *base_peer;
1520  char other_side[AST_CHANNEL_NAME];
1521  char *c;
1522 
1523  ast_copy_string(other_side, event_from, sizeof(other_side));
1524  if ((c = strrchr(other_side, ';'))) {
1525  *++c = '1';
1526  }
1527  if ((tmpchan = ast_channel_get_by_name(other_side))) {
1528  ast_channel_lock(tmpchan);
1529  if ((base_peer = ast_bridged_channel(tmpchan))) {
1530  ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
1531  }
1532  ast_channel_unlock(tmpchan);
1533  tmpchan = ast_channel_unref(tmpchan);
1534  }
1535  } else {
1536  ast_copy_string(pu->peername, event_from, sizeof(pu->peername));
1537  }
1538  } else {
1539  event_from = S_OR(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"), chan->name);
1540  }
1541 
1542  /*
1543  * Remember what had been dialed, so that if the parking
1544  * expires, we try to come back to the same place
1545  */
1547 
1548  /*
1549  * If extension has options specified, they override all other
1550  * possibilities such as the returntoorigin flag and transferred
1551  * context. Information on extension options is lost here, so
1552  * we set a flag
1553  */
1554  ast_copy_string(pu->context,
1555  S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)),
1556  sizeof(pu->context));
1557  ast_copy_string(pu->exten,
1558  S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)),
1559  sizeof(pu->exten));
1560  pu->priority = args->return_pri ? args->return_pri :
1561  (chan->macropriority ? chan->macropriority : chan->priority);
1562 
1563  /* Mark channel as parked */
1564  pbx_builtin_setvar_helper(pu->chan, "PARKED_CALL", "1");
1565 
1566  /*
1567  * If parking a channel directly, don't quite yet get parking
1568  * running on it. All parking lot entries are put into the
1569  * parking lot with notquiteyet on.
1570  */
1571  if (peer != chan) {
1572  pu->notquiteyet = 0;
1573  }
1574 
1575  /* Wake up the (presumably select()ing) thread */
1576  pthread_kill(parking_thread, SIGURG);
1577  ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n",
1578  chan->name, pu->parkingnum, pu->parkinglot->name,
1579  pu->context, pu->exten, pu->priority, (pu->parkingtime / 1000));
1580 
1581  ast_cel_report_event(chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
1582 
1583  ast_manager_event(chan, EVENT_FLAG_CALL, "ParkedCall",
1584  "Exten: %s\r\n"
1585  "Channel: %s\r\n"
1586  "Parkinglot: %s\r\n"
1587  "From: %s\r\n"
1588  "Timeout: %ld\r\n"
1589  "CallerIDNum: %s\r\n"
1590  "CallerIDName: %s\r\n"
1591  "ConnectedLineNum: %s\r\n"
1592  "ConnectedLineName: %s\r\n"
1593  "Uniqueid: %s\r\n",
1594  pu->parkingexten, chan->name, pu->parkinglot->name, event_from,
1595  (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
1596  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<unknown>"),
1597  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>"),
1598  S_COR(chan->connected.id.number.valid, chan->connected.id.number.str, "<unknown>"),
1599  S_COR(chan->connected.id.name.valid, chan->connected.id.name.str, "<unknown>"),
1600  chan->uniqueid
1601  );
1602  ast_debug(4, "peer->name: %s\n", peer ? peer->name : "-No peer-");
1603  ast_debug(4, "args->orig_chan_name: %s\n", args->orig_chan_name ? args->orig_chan_name : "-none-");
1604  ast_debug(4, "pu->peername: %s\n", pu->peername);
1605  ast_debug(4, "AMI ParkedCall Channel: %s\n", chan->name);
1606  ast_debug(4, "AMI ParkedCall From: %s\n", event_from);
1607 
1608  if (peer && adsipark && ast_adsi_available(peer)) {
1609  adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
1611  }
1612 
1613  snprintf(app_data, sizeof(app_data), "%s,%s", pu->parkingexten,
1614  pu->parkinglot->name);
1616  NULL, NULL, parkedcall, ast_strdup(app_data), ast_free_ptr, registrar)) {
1617  ast_log(LOG_ERROR, "Could not create parked call exten: %s@%s\n",
1619  } else {
1621  }
1622 
1624 
1625  /* Only say number if it's a number and the channel hasn't been masqueraded away */
1626  if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE)
1627  && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) {
1628  /*
1629  * If a channel is masqueraded into peer while playing back the
1630  * parking space number do not continue playing it back. This
1631  * is the case if an attended transfer occurs.
1632  */
1634  /* Tell the peer channel the number of the parking space */
1635  ast_say_digits(peer, pu->parkingnum, "", peer->language);
1637  }
1638  if (peer == chan) { /* pu->notquiteyet = 1 */
1639  /* Wake up parking thread if we're really done */
1640  if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
1643  } else {
1646  S_OR(pu->parkinglot->cfg.mohclass, NULL),
1647  !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
1648  }
1649  pu->notquiteyet = 0;
1650  pthread_kill(parking_thread, SIGURG);
1651  }
1652  return 0;
1653 }
1654 
1655 int ast_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
1656 {
1657  int res;
1658  char *parse;
1659  const char *app_data;
1660  struct ast_exten *exten;
1661  struct park_app_args app_args;
1662  struct ast_park_call_args args = {
1663  .timeout = timeout,
1664  .extout = extout,
1665  };
1666 
1667  if (!park_exten || !park_context) {
1668  return park_call_full(park_me, parker, &args);
1669  }
1670 
1671  /*
1672  * Determiine if the specified park extension has an exclusive
1673  * parking lot to use.
1674  */
1675  if (parker && parker != park_me) {
1676  ast_autoservice_start(park_me);
1677  }
1678  exten = get_parking_exten(park_exten, parker, park_context);
1679  if (exten) {
1680  app_data = ast_get_extension_app_data(exten);
1681  if (!app_data) {
1682  app_data = "";
1683  }
1684  parse = ast_strdupa(app_data);
1685  AST_STANDARD_APP_ARGS(app_args, parse);
1686 
1687  if (!ast_strlen_zero(app_args.pl_name)) {
1688  /* Find the specified exclusive parking lot */
1689  args.parkinglot = find_parkinglot(app_args.pl_name);
1690  if (!args.parkinglot && parkeddynamic) {
1691  args.parkinglot = create_dynamic_parkinglot(app_args.pl_name, park_me);
1692  }
1693  }
1694  }
1695  if (parker && parker != park_me) {
1696  ast_autoservice_stop(park_me);
1697  }
1698 
1699  res = park_call_full(park_me, parker, &args);
1700  if (args.parkinglot) {
1702  }
1703  return res;
1704 }
1705 
1706 int ast_park_call(struct ast_channel *park_me, struct ast_channel *parker, int timeout, const char *park_exten, int *extout)
1707 {
1708  struct ast_park_call_args args = {
1709  .timeout = timeout,
1710  .extout = extout,
1711  };
1712 
1713  return park_call_full(park_me, parker, &args);
1714 }
1715 
1716 /*!
1717  * \brief Park call via masqueraded channel and announce parking spot on peer channel.
1718  *
1719  * \param rchan the real channel to be parked
1720  * \param peer the channel to have the parking read to.
1721  * \param args Additional parking options when parking a call.
1722  *
1723  * \retval 0 on success.
1724  * \retval -1 on failure.
1725  */
1726 static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
1727 {
1728  struct ast_channel *chan;
1729 
1730  /* Make a new, channel that we'll use to masquerade in the real one */
1731  chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten,
1732  rchan->context, rchan->linkedid, rchan->amaflags, "Parked/%s", rchan->name);
1733  if (!chan) {
1734  ast_log(LOG_WARNING, "Unable to create parked channel\n");
1735  if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1736  if (peer == rchan) {
1737  /* Only have one channel to worry about. */
1738  ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1739  } else if (peer) {
1740  /* Have two different channels to worry about. */
1741  play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1742  }
1743  }
1744  return -1;
1745  }
1746 
1747  args->pu = park_space_reserve(rchan, peer, args);
1748  if (!args->pu) {
1749  ast_hangup(chan);
1750  if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1751  if (peer == rchan) {
1752  /* Only have one channel to worry about. */
1753  ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1754  } else if (peer) {
1755  /* Have two different channels to worry about. */
1756  play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1757  }
1758  }
1759  return -1;
1760  }
1761 
1762  /* Make formats okay */
1763  chan->readformat = rchan->readformat;
1764  chan->writeformat = rchan->writeformat;
1765 
1766  if (ast_channel_masquerade(chan, rchan)) {
1767  park_space_abort(args->pu);
1768  args->pu = NULL;
1769  ast_hangup(chan);
1770  if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1771  if (peer == rchan) {
1772  /* Only have one channel to worry about. */
1773  ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1774  } else if (peer) {
1775  /* Have two different channels to worry about. */
1776  play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1777  }
1778  }
1779  return -1;
1780  }
1781 
1782  /* Setup the extensions and such */
1783  set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
1784 
1785  /* Setup the macro extension and such */
1786  ast_copy_string(chan->macrocontext,rchan->macrocontext,sizeof(chan->macrocontext));
1787  ast_copy_string(chan->macroexten,rchan->macroexten,sizeof(chan->macroexten));
1788  chan->macropriority = rchan->macropriority;
1789 
1790  /* Manually do the masquerade to make sure it is complete. */
1791  ast_do_masquerade(chan);
1792 
1793  if (peer == rchan) {
1794  peer = chan;
1795  }
1796 
1797  /* parking space reserved, return code check unnecessary */
1798  park_call_full(chan, peer, args);
1799 
1800  return 0;
1801 }
1802 
1803 int ast_masq_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
1804 {
1805  int res;
1806  char *parse;
1807  const char *app_data;
1808  struct ast_exten *exten;
1809  struct park_app_args app_args;
1810  struct ast_park_call_args args = {
1811  .timeout = timeout,
1812  .extout = extout,
1813  };
1814 
1815  if (parker) {
1816  args.orig_chan_name = ast_strdupa(parker->name);
1817  }
1818  if (!park_exten || !park_context) {
1819  return masq_park_call(park_me, parker, &args);
1820  }
1821 
1822  /*
1823  * Determiine if the specified park extension has an exclusive
1824  * parking lot to use.
1825  */
1826  if (parker && parker != park_me) {
1827  ast_autoservice_start(park_me);
1828  }
1829  exten = get_parking_exten(park_exten, parker, park_context);
1830  if (exten) {
1831  app_data = ast_get_extension_app_data(exten);
1832  if (!app_data) {
1833  app_data = "";
1834  }
1835  parse = ast_strdupa(app_data);
1836  AST_STANDARD_APP_ARGS(app_args, parse);
1837 
1838  if (!ast_strlen_zero(app_args.pl_name)) {
1839  /* Find the specified exclusive parking lot */
1840  args.parkinglot = find_parkinglot(app_args.pl_name);
1841  if (!args.parkinglot && parkeddynamic) {
1842  args.parkinglot = create_dynamic_parkinglot(app_args.pl_name, park_me);
1843  }
1844  }
1845  }
1846  if (parker && parker != park_me) {
1847  ast_autoservice_stop(park_me);
1848  }
1849 
1850  res = masq_park_call(park_me, parker, &args);
1851  if (args.parkinglot) {
1853  }
1854  return res;
1855 }
1856 
1857 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
1858 {
1859  struct ast_park_call_args args = {
1860  .timeout = timeout,
1861  .extout = extout,
1862  };
1863 
1864  if (peer) {
1865  args.orig_chan_name = ast_strdupa(peer->name);
1866  }
1867  return masq_park_call(rchan, peer, &args);
1868 }
1869 
1870 static int finishup(struct ast_channel *chan)
1871 {
1873 
1874  return ast_autoservice_stop(chan);
1875 }
1876 
1877 /*!
1878  * \internal
1879  * \brief Builtin transfer park call helper.
1880  *
1881  * \param park_me Channel to be parked.
1882  * \param parker Channel parking the call.
1883  * \param park_exten Parking lot dialplan access ramp extension.
1884  *
1885  * \note Assumes park_me is on hold and in autoservice.
1886  *
1887  * \retval -1 on successful park.
1888  * \retval -1 on park_me hangup.
1889  * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
1890  */
1891 static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
1892 {
1893  char *parse;
1894  const char *app_data;
1895  const char *pl_name;
1896  struct ast_park_call_args args = { 0, };
1897  struct park_app_args app_args;
1898  int res;
1899 
1900  app_data = ast_get_extension_app_data(park_exten);
1901  if (!app_data) {
1902  app_data = "";
1903  }
1904  parse = ast_strdupa(app_data);
1905  AST_STANDARD_APP_ARGS(app_args, parse);
1906 
1907  /* Find the parking lot */
1908  if (!ast_strlen_zero(app_args.pl_name)) {
1909  pl_name = app_args.pl_name;
1910  } else {
1911  pl_name = findparkinglotname(parker);
1912  }
1913  if (ast_strlen_zero(pl_name)) {
1914  /* Parking lot is not specified, so use the default parking lot. */
1916  } else {
1917  args.parkinglot = find_parkinglot(pl_name);
1918  if (!args.parkinglot && parkeddynamic) {
1919  args.parkinglot = create_dynamic_parkinglot(pl_name, park_me);
1920  }
1921  }
1922 
1923  if (args.parkinglot) {
1924  /* Park the call */
1925  res = finishup(park_me);
1926  if (res) {
1927  /* park_me hungup on us. */
1929  return -1;
1930  }
1931  res = masq_park_call(park_me, parker, &args);
1933  } else {
1934  /* Parking failed because parking lot does not exist. */
1935  if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
1936  ast_stream_and_wait(parker, "pbx-parkingfailed", "");
1937  }
1938  finishup(park_me);
1939  res = -1;
1940  }
1941 
1942  return res ? AST_FEATURE_RETURN_SUCCESS : -1;
1943 }
1944 
1945 /*!
1946  * \brief set caller and callee according to the direction
1947  * \param caller, callee, peer, chan, sense
1948  *
1949  * Detect who triggered feature and set callee/caller variables accordingly
1950  */
1951 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
1952  struct ast_channel *peer, struct ast_channel *chan, int sense)
1953 {
1954  if (sense == FEATURE_SENSE_PEER) {
1955  *caller = peer;
1956  *callee = chan;
1957  } else {
1958  *callee = peer;
1959  *caller = chan;
1960  }
1961 }
1962 
1963 /*!
1964  * \brief support routing for one touch call parking
1965  * \param chan channel parking call
1966  * \param peer channel to be parked
1967  * \param config unsed
1968  * \param code unused
1969  * \param sense feature options
1970  * \param data unused
1971  *
1972  * \retval -1 on successful park.
1973  * \retval -1 on chan hangup.
1974  * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
1975  */
1976 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1977 {
1978  struct ast_channel *parker;
1979  struct ast_channel *parkee;
1980  struct ast_park_call_args args = { 0, };
1981 
1982  /*
1983  * We used to set chan's exten and priority to "s" and 1 here,
1984  * but this generates (in some cases) an invalid extension, and
1985  * if "s" exists, could errantly cause execution of extensions
1986  * you don't expect. It makes more sense to let nature take its
1987  * course when chan finishes, and let the pbx do its thing and
1988  * hang up when the park is over.
1989  */
1990 
1991  /* Answer if call is not up */
1992  if (chan->_state != AST_STATE_UP) {
1993  /*
1994  * XXX Why are we doing this? Both of the channels should be up
1995  * since you cannot do DTMF features unless you are bridged.
1996  */
1997  if (ast_answer(chan)) {
1998  return -1;
1999  }
2000 
2001  /* Sleep to allow VoIP streams to settle down */
2002  if (ast_safe_sleep(chan, 1000)) {
2003  return -1;
2004  }
2005  }
2006 
2007  /* one direction used to call park_call.... */
2008  set_peers(&parker, &parkee, peer, chan, sense);
2009  return masq_park_call(parkee, parker, &args) ? AST_FEATURE_RETURN_SUCCESS : -1;
2010 }
2011 
2012 /*!
2013  * \internal
2014  * \brief Play file to specified channel.
2015  *
2016  * \param play_to Channel to play audiofile to.
2017  * \param other Channel to put in autoservice while playing file.
2018  * \param msg Descriptive name of message type being played.
2019  * \param audiofile Audio file to play.
2020  *
2021  * \retval 0 on success.
2022  * \retval -1 on error. (Couldn't play file, a channel hung up,...)
2023  */
2024 static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
2025 {
2026  /* Put other channel in autoservice. */
2027  if (ast_autoservice_start(other)) {
2028  return -1;
2029  }
2032  if (ast_stream_and_wait(play_to, audiofile, "")) {
2033  ast_log(LOG_WARNING, "Failed to play %s '%s'!\n", msg, audiofile);
2034  ast_autoservice_stop(other);
2035  return -1;
2036  }
2037  if (ast_autoservice_stop(other)) {
2038  return -1;
2039  }
2040  return 0;
2041 }
2042 
2043 /*!
2044  * \internal
2045  * \brief Play file to specified channels.
2046  *
2047  * \param left Channel on left to play file.
2048  * \param right Channel on right to play file.
2049  * \param which Play file on indicated channels: which < 0 play left, which == 0 play both, which > 0 play right
2050  * \param msg Descriptive name of message type being played.
2051  * \param audiofile Audio file to play to channels.
2052  *
2053  * \note Plays file to the indicated channels in turn so please
2054  * don't use this for very long messages.
2055  *
2056  * \retval 0 on success.
2057  * \retval -1 on error. (Couldn't play file, channel hung up,...)
2058  */
2059 static int play_message_to_chans(struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
2060 {
2061  /* First play the file to the left channel if requested. */
2062  if (which <= 0 && play_message_on_chan(left, right, msg, audiofile)) {
2063  return -1;
2064  }
2065 
2066  /* Then play the file to the right channel if requested. */
2067  if (which >= 0 && play_message_on_chan(right, left, msg, audiofile)) {
2068  return -1;
2069  }
2070 
2071  return 0;
2072 }
2073 
2074 /*!
2075  * \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
2076  * other channel during the message, so please don't use this for very long messages
2077  */
2078 static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
2079 {
2080  return play_message_to_chans(caller_chan, callee_chan, 0, "automon message",
2081  audiofile);
2082 }
2083 
2084 /*!
2085  * \brief Monitor a channel by DTMF
2086  * \param chan channel requesting monitor
2087  * \param peer channel to be monitored
2088  * \param config
2089  * \param code
2090  * \param sense feature options
2091  *
2092  * \param data
2093  * Check monitor app enabled, setup channels, both caller/callee chans not null
2094  * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
2095  * \retval AST_FEATURE_RETURN_SUCCESS on success.
2096  * \retval -1 on error.
2097  */
2098 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2099 {
2100  char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
2101  int x = 0;
2102  size_t len;
2103  struct ast_channel *caller_chan, *callee_chan;
2104  const char *automon_message_start = NULL;
2105  const char *automon_message_stop = NULL;
2106  const char *touch_format = NULL;
2107  const char *touch_monitor = NULL;
2108  const char *touch_monitor_prefix = NULL;
2109 
2110  if (!monitor_ok) {
2111  ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
2112  return -1;
2113  }
2114 
2115  if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
2116  monitor_ok = 0;
2117  ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
2118  return -1;
2119  }
2120 
2121  set_peers(&caller_chan, &callee_chan, peer, chan, sense);
2122 
2123  /* Find extra messages */
2124  automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
2125  automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
2126 
2127  if (!ast_strlen_zero(courtesytone)) { /* Play courtesy tone if configured */
2128  if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
2129  return -1;
2130  }
2131  }
2132 
2133  if (callee_chan->monitor) {
2134  manager_event(EVENT_FLAG_USER, "UserEvent",
2135  "UserEvent: StopRec\r\n"
2136  "Uniqueid: %s\r\n",
2137  caller_chan->uniqueid);
2138  ast_verb(4, "User hit '%s' to stop recording call.\n", code);
2139  if (!ast_strlen_zero(automon_message_stop)) {
2140  play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
2141  }
2142  callee_chan->monitor->stop(callee_chan, 1);
2144  }
2145 
2146  touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
2147  touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
2148  touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
2149 
2150  if (!touch_format)
2151  touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
2152 
2153  if (!touch_monitor)
2154  touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
2155 
2156  if (!touch_monitor_prefix)
2157  touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
2158 
2159  if (touch_monitor) {
2160  len = strlen(touch_monitor) + 50;
2161  args = ast_alloca(len);
2162  touch_filename = ast_alloca(len);
2163  snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
2164  snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
2165  } else {
2166  caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
2167  caller_chan->caller.id.number.str, caller_chan->name));
2168  callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
2169  callee_chan->caller.id.number.str, callee_chan->name));
2170  len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
2171  args = ast_alloca(len);
2172  touch_filename = ast_alloca(len);
2173  snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
2174  snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
2175  }
2176 
2177  for(x = 0; x < strlen(args); x++) {
2178  if (args[x] == '/')
2179  args[x] = '-';
2180  }
2181 
2182  manager_event(EVENT_FLAG_USER, "UserEvent",
2183  "UserEvent: Rec\r\n"
2184  "Uniqueid: %s\r\n"
2185  "FileName: %s\r\n",
2186  caller_chan->uniqueid, touch_filename);
2187  ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
2188 
2189  pbx_exec(callee_chan, monitor_app, args);
2190  pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
2191  pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
2192 
2193  if (!ast_strlen_zero(automon_message_start)) { /* Play start message for both channels */
2194  play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
2195  }
2196 
2198 }
2199 
2200 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2201 {
2202  char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
2203  int x = 0;
2204  size_t len;
2205  struct ast_channel *caller_chan, *callee_chan;
2206  const char *mixmonitor_spy_type = "MixMonitor";
2207  const char *touch_format;
2208  const char *touch_monitor;
2209  int count = 0;
2210 
2211  if (!mixmonitor_ok) {
2212  ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
2213  return -1;
2214  }
2215 
2216  if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
2217  mixmonitor_ok = 0;
2218  ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
2219  return -1;
2220  }
2221 
2222  set_peers(&caller_chan, &callee_chan, peer, chan, sense);
2223 
2224  if (!ast_strlen_zero(courtesytone)) {
2225  if (ast_autoservice_start(callee_chan))
2226  return -1;
2228  if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
2229  ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2230  ast_autoservice_stop(callee_chan);
2231  return -1;
2232  }
2233  if (ast_autoservice_stop(callee_chan))
2234  return -1;
2235  }
2236 
2237  ast_channel_lock(callee_chan);
2238  count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
2239  ast_channel_unlock(callee_chan);
2240 
2241  /* This means a mixmonitor is attached to the channel, running or not is unknown. */
2242  if (count > 0) {
2243  ast_verb(3, "User hit '%s' to stop recording call.\n", code);
2244 
2245  /* Make sure they are running */
2246  ast_channel_lock(callee_chan);
2247  count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
2248  ast_channel_unlock(callee_chan);
2249  if (count > 0) {
2250  if (!stopmixmonitor_ok) {
2251  ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2252  return -1;
2253  }
2254  if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
2255  stopmixmonitor_ok = 0;
2256  ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2257  return -1;
2258  } else {
2259  pbx_exec(callee_chan, stopmixmonitor_app, "");
2261  }
2262  }
2263 
2264  ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
2265  }
2266 
2267  touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
2268  touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
2269 
2270  if (!touch_format)
2271  touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
2272 
2273  if (!touch_monitor)
2274  touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
2275 
2276  if (touch_monitor) {
2277  len = strlen(touch_monitor) + 50;
2278  args = ast_alloca(len);
2279  touch_filename = ast_alloca(len);
2280  snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
2281  snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
2282  } else {
2283  caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
2284  caller_chan->caller.id.number.str, caller_chan->name));
2285  callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
2286  callee_chan->caller.id.number.str, callee_chan->name));
2287  len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
2288  args = ast_alloca(len);
2289  touch_filename = ast_alloca(len);
2290  snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
2291  snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
2292  }
2293 
2294  for( x = 0; x < strlen(args); x++) {
2295  if (args[x] == '/')
2296  args[x] = '-';
2297  }
2298 
2299  ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
2300 
2301  pbx_exec(callee_chan, mixmonitor_app, args);
2302  pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
2303  pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
2305 }
2306 
2307 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2308 {
2309  ast_verb(4, "User hit '%s' to disconnect call.\n", code);
2311 }
2312 
2313 /*!
2314  * \brief Find the context for the transfer
2315  * \param transferer
2316  * \param transferee
2317  *
2318  * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
2319  * \return a context string
2320  */
2321 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
2322 {
2323  const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
2324  if (ast_strlen_zero(s)) {
2325  s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
2326  }
2327  if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
2328  s = transferer->macrocontext;
2329  }
2330  if (ast_strlen_zero(s)) {
2331  s = transferer->context;
2332  }
2333  return s;
2334 }
2335 
2336 /*!
2337  * \brief Blind transfer user to another extension
2338  * \param chan channel to be transferred
2339  * \param peer channel initiated blind transfer
2340  * \param config
2341  * \param code
2342  * \param data
2343  * \param sense feature options
2344  *
2345  * Place chan on hold, check if transferred to parkinglot extension,
2346  * otherwise check extension exists and transfer caller.
2347  * \retval AST_FEATURE_RETURN_SUCCESS.
2348  * \retval -1 on failure.
2349  */
2350 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2351 {
2352  struct ast_channel *transferer;
2353  struct ast_channel *transferee;
2354  struct ast_exten *park_exten;
2355  const char *transferer_real_context;
2356  char xferto[256] = "";
2357  int res;
2358 
2359  ast_debug(1, "Executing Blind Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
2360  set_peers(&transferer, &transferee, peer, chan, sense);
2361  transferer_real_context = real_ctx(transferer, transferee);
2362 
2363  /* Start autoservice on transferee while we talk to the transferer */
2364  ast_autoservice_start(transferee);
2365  ast_indicate(transferee, AST_CONTROL_HOLD);
2366 
2367  /* Transfer */
2368  res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2369  if (res < 0) {
2370  finishup(transferee);
2371  return -1; /* error ? */
2372  }
2373  if (res > 0) { /* If they've typed a digit already, handle it */
2374  xferto[0] = (char) res;
2375  }
2376 
2377  res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2378  if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
2379  finishup(transferee);
2380  return -1;
2381  }
2382  if (res == 0) {
2383  if (xferto[0]) {
2384  ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2385  xferto, transferer_real_context);
2386  } else {
2387  /* Does anyone care about this case? */
2388  ast_log(LOG_WARNING, "No digits dialed.\n");
2389  }
2390  ast_stream_and_wait(transferer, "pbx-invalid", "");
2391  finishup(transferee);
2393  }
2394 
2395  park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
2396  if (park_exten) {
2397  /* We are transfering the transferee to a parking lot. */
2398  return xfer_park_call_helper(transferee, transferer, park_exten);
2399  }
2400 
2401  /* Do blind transfer. */
2402  ast_verb(3, "Blind transferring %s to '%s' (context %s) priority 1\n",
2403  transferee->name, xferto, transferer_real_context);
2404  ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
2405  pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
2406  pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
2407  finishup(transferee);
2408  ast_channel_lock(transferer);
2409  if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
2410  transferer->cdr = ast_cdr_alloc();
2411  if (transferer->cdr) {
2412  ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
2413  ast_cdr_start(transferer->cdr);
2414  }
2415  }
2416  ast_channel_unlock(transferer);
2417  if (transferer->cdr) {
2418  struct ast_cdr *swap = transferer->cdr;
2419 
2420  ast_debug(1,
2421  "transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
2422  transferer->name, transferee->name, transferer->cdr->lastapp,
2423  transferer->cdr->lastdata, transferer->cdr->channel,
2424  transferer->cdr->dstchannel);
2425  ast_debug(1, "TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
2426  transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel,
2427  transferee->cdr->dstchannel);
2428  ast_debug(1, "transferer_real_context=%s; xferto=%s\n",
2429  transferer_real_context, xferto);
2430  /* swap cdrs-- it will save us some time & work */
2431  transferer->cdr = transferee->cdr;
2432  transferee->cdr = swap;
2433  }
2434  if (!transferee->pbx) {
2435  /* Doh! Use our handy async_goto functions */
2436  ast_debug(1, "About to ast_async_goto %s.\n", transferee->name);
2437  if (ast_async_goto(transferee, transferer_real_context, xferto, 1)) {
2438  ast_log(LOG_WARNING, "Async goto failed :-(\n");
2439  }
2440 
2441  /* The transferee is masqueraded and the original bridged channels can be hungup. */
2442  res = -1;
2443  } else {
2444  /* Set the transferee's new extension, since it exists, using transferer context */
2445  ast_debug(1, "About to explicit goto %s, it has a PBX.\n", transferee->name);
2446  ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
2447  set_c_e_p(transferee, transferer_real_context, xferto, 0);
2448 
2449  /*
2450  * Break the bridge. The transferee needs to resume executing
2451  * dialplan at the xferto location.
2452  */
2454  }
2455  check_goto_on_transfer(transferer);
2456  return res;
2457 }
2458 
2459 /*!
2460  * \brief make channels compatible
2461  * \param c
2462  * \param newchan
2463  * \retval 0 on success.
2464  * \retval -1 on failure.
2465  */
2466 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
2467 {
2468  if (ast_channel_make_compatible(c, newchan) < 0) {
2469  ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
2470  c->name, newchan->name);
2471  ast_hangup(newchan);
2472  return -1;
2473  }
2474  return 0;
2475 }
2476 
2477 /*!
2478  * \internal
2479  * \brief Builtin attended transfer failed cleanup.
2480  * \since 1.10
2481  *
2482  * \param transferee Party A in the transfer.
2483  * \param transferer Party B in the transfer.
2484  * \param connected_line Saved connected line info about party A.
2485  *
2486  * \note The connected_line data is freed.
2487  *
2488  * \return Nothing
2489  */
2490 static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
2491 {
2492  finishup(transferee);
2493 
2494  /*
2495  * Restore party B connected line info about party A.
2496  *
2497  * Party B was the caller to party C and is the last known mode
2498  * for party B.
2499  */
2500  if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
2501  ast_channel_update_connected_line(transferer, connected_line, NULL);
2502  }
2503  ast_party_connected_line_free(connected_line);
2504 }
2505 
2506 /*!
2507  * \brief Attended transfer
2508  * \param chan transferred user
2509  * \param peer person transfering call
2510  * \param config
2511  * \param code
2512  * \param sense feature options
2513  *
2514  * \param data
2515  * Get extension to transfer to, if you cannot generate channel (or find extension)
2516  * return to host channel. After called channel answered wait for hangup of transferer,
2517  * bridge call between transfer peer (taking them off hold) to attended transfer channel.
2518  *
2519  * \return -1 on failure
2520  */
2521 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2522 {
2523  struct ast_channel *transferer;/* Party B */
2524  struct ast_channel *transferee;/* Party A */
2525  struct ast_exten *park_exten;
2526  const char *chan1_attended_sound;
2527  const char *chan2_attended_sound;
2528  const char *transferer_real_context;
2529  char xferto[256] = "";
2530  int res;
2531  int outstate=0;
2532  struct ast_channel *newchan;
2533  struct ast_channel *xferchan;
2534  struct ast_bridge_thread_obj *tobj;
2535  struct ast_bridge_config bconfig;
2536  int l;
2537  struct ast_party_connected_line connected_line;
2538  struct ast_datastore *features_datastore;
2539  struct ast_dial_features *dialfeatures;
2540  char *transferer_tech;
2541  char *transferer_name;
2542  char *transferer_name_orig;
2543  char *dash;
2544 
2545  ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
2546  set_peers(&transferer, &transferee, peer, chan, sense);
2547  transferer_real_context = real_ctx(transferer, transferee);
2548 
2549  /* Start autoservice on transferee while we talk to the transferer */
2550  ast_autoservice_start(transferee);
2551  ast_indicate(transferee, AST_CONTROL_HOLD);
2552 
2553  /* Transfer */
2554  res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2555  if (res < 0) {
2556  finishup(transferee);
2557  return -1;
2558  }
2559  if (res > 0) { /* If they've typed a digit already, handle it */
2560  xferto[0] = (char) res;
2561  }
2562 
2563  /* this is specific of atxfer */
2564  res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2565  if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
2566  finishup(transferee);
2567  return -1;
2568  }
2569  l = strlen(xferto);
2570  if (res == 0) {
2571  if (l) {
2572  ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2573  xferto, transferer_real_context);
2574  } else {
2575  /* Does anyone care about this case? */
2576  ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
2577  }
2578  ast_stream_and_wait(transferer, "pbx-invalid", "");
2579  finishup(transferee);
2581  }
2582 
2583  park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
2584  if (park_exten) {
2585  /* We are transfering the transferee to a parking lot. */
2586  return xfer_park_call_helper(transferee, transferer, park_exten);
2587  }
2588 
2589  /*
2590  * Append context to dialed transfer number.
2591  *
2592  * NOTE: The local channel needs the /n flag so party C will use
2593  * the feature flags set by the dialplan when calling that
2594  * party.
2595  */
2596  snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
2597 
2598  /* If we are performing an attended transfer and we have two channels involved then
2599  copy sound file information to play upon attended transfer completion */
2600  chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2601  chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2602  if (!ast_strlen_zero(chan1_attended_sound)) {
2603  pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
2604  }
2605  if (!ast_strlen_zero(chan2_attended_sound)) {
2606  pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
2607  }
2608 
2609  /* Extract redial transferer information from the channel name. */
2610  transferer_name_orig = ast_strdupa(transferer->name);
2611  transferer_name = ast_strdupa(transferer_name_orig);
2612  transferer_tech = strsep(&transferer_name, "/");
2613  dash = strrchr(transferer_name, '-');
2614  if (dash) {
2615  /* Trim off channel name sequence/serial number. */
2616  *dash = '\0';
2617  }
2618 
2619  /* Stop autoservice so we can monitor all parties involved in the transfer. */
2620  if (ast_autoservice_stop(transferee) < 0) {
2621  ast_indicate(transferee, AST_CONTROL_UNHOLD);
2622  return -1;
2623  }
2624 
2625  /* Save connected line info for party B about party A in case transfer fails. */
2626  ast_party_connected_line_init(&connected_line);
2627  ast_channel_lock(transferer);
2628  ast_party_connected_line_copy(&connected_line, &transferer->connected);
2629  ast_channel_unlock(transferer);
2631 
2632  /* Dial party C */
2633  newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
2634  transferee, "Local", ast_best_codec(transferer->nativeformats), xferto,
2635  atxfernoanswertimeout, &outstate, transferer->language);
2636  ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
2637 
2638  if (!ast_check_hangup(transferer)) {
2639  int hangup_dont = 0;
2640 
2641  /* Transferer (party B) is up */
2642  ast_debug(1, "Actually doing an attended transfer.\n");
2643 
2644  /* Start autoservice on transferee while the transferer deals with party C. */
2645  ast_autoservice_start(transferee);
2646 
2647  ast_indicate(transferer, -1);
2648  if (!newchan) {
2649  /* any reason besides user requested cancel and busy triggers the failed sound */
2650  switch (outstate) {
2651  case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
2652  case AST_CONTROL_BUSY:
2654  if (ast_stream_and_wait(transferer, xfersound, "")) {
2655  ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2656  }
2657  break;
2658  default:
2659  if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2660  ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2661  }
2662  break;
2663  }
2664  atxfer_fail_cleanup(transferee, transferer, &connected_line);
2666  }
2667 
2668  if (check_compat(transferer, newchan)) {
2669  if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2670  ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2671  }
2672  atxfer_fail_cleanup(transferee, transferer, &connected_line);
2674  }
2675  memset(&bconfig,0,sizeof(struct ast_bridge_config));
2678 
2679  /*
2680  * ast_bridge_call clears AST_FLAG_BRIDGE_HANGUP_DONT, but we
2681  * don't want that to happen here because the transferer is in
2682  * another bridge already.
2683  */
2684  if (ast_test_flag(transferer, AST_FLAG_BRIDGE_HANGUP_DONT)) {
2685  hangup_dont = 1;
2686  }
2687 
2688  /*
2689  * Don't let the after-bridge code run the h-exten. It is the
2690  * wrong bridge to run the h-exten after.
2691  */
2693 
2694  /*
2695  * Let party B and C talk as long as they want while party A
2696  * languishes in autoservice listening to MOH.
2697  */
2698  ast_bridge_call(transferer, newchan, &bconfig);
2699 
2700  if (hangup_dont) {
2701  /* Restore the AST_FLAG_BRIDGE_HANGUP_DONT flag */
2703  }
2704 
2705  if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
2706  ast_hangup(newchan);
2707  if (ast_stream_and_wait(transferer, xfersound, "")) {
2708  ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2709  }
2710  atxfer_fail_cleanup(transferee, transferer, &connected_line);
2712  }
2713 
2714  /* Transferer (party B) is confirmed hung up at this point. */
2715  if (check_compat(transferee, newchan)) {
2716  finishup(transferee);
2717  ast_party_connected_line_free(&connected_line);
2718  return -1;
2719  }
2720 
2721  ast_indicate(transferee, AST_CONTROL_UNHOLD);
2722  if ((ast_autoservice_stop(transferee) < 0)
2723  || (ast_waitfordigit(transferee, 100) < 0)
2724  || (ast_waitfordigit(newchan, 100) < 0)
2725  || ast_check_hangup(transferee)
2726  || ast_check_hangup(newchan)) {
2727  ast_hangup(newchan);
2728  ast_party_connected_line_free(&connected_line);
2729  return -1;
2730  }
2731  } else if (!ast_check_hangup(transferee)) {
2732  /* Transferer (party B) has hung up at this point. Doing blonde transfer. */
2733  ast_debug(1, "Actually doing a blonde transfer.\n");
2734 
2735  if (!newchan && !atxferdropcall) {
2736  /* Party C is not available, try to call party B back. */
2737  unsigned int tries = 0;
2738 
2739  if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
2741  "Transferer channel name: '%s' cannot be used for callback.\n",
2742  transferer_name_orig);
2743  ast_indicate(transferee, AST_CONTROL_UNHOLD);
2744  ast_party_connected_line_free(&connected_line);
2745  return -1;
2746  }
2747 
2748  tries = 0;
2749  for (;;) {
2750  /* Try to get party B back. */
2751  ast_debug(1, "We're trying to callback %s/%s\n",
2752  transferer_tech, transferer_name);
2753  newchan = feature_request_and_dial(transferer, transferer_name_orig,
2754  transferee, transferee, transferer_tech,
2755  ast_best_codec(transferee->nativeformats), transferer_name,
2756  atxfernoanswertimeout, &outstate, transferer->language);
2757  ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
2758  !!newchan, outstate);
2759  if (newchan) {
2760  /*
2761  * We have recalled party B (newchan). We need to give this
2762  * call leg the same feature flags as the original party B call
2763  * leg.
2764  */
2765  ast_channel_lock(transferer);
2766  features_datastore = ast_channel_datastore_find(transferer,
2767  &dial_features_info, NULL);
2768  if (features_datastore && (dialfeatures = features_datastore->data)) {
2769  struct ast_flags my_features = { 0 };
2770  struct ast_flags peer_features = { 0 };
2771 
2772  ast_copy_flags(&my_features, &dialfeatures->my_features,
2773  AST_FLAGS_ALL);
2774  ast_copy_flags(&peer_features, &dialfeatures->peer_features,
2775  AST_FLAGS_ALL);
2776  ast_channel_unlock(transferer);
2777  add_features_datastore(newchan, &my_features, &peer_features);
2778  } else {
2779  ast_channel_unlock(transferer);
2780  }
2781  break;
2782  }
2783  if (ast_check_hangup(transferee)) {
2784  break;
2785  }
2786 
2787  ++tries;
2788  if (atxfercallbackretries <= tries) {
2789  /* No more callback tries remaining. */
2790  break;
2791  }
2792 
2793  if (atxferloopdelay) {
2794  /* Transfer failed, sleeping */
2795  ast_debug(1, "Sleeping for %u ms before retrying atxfer.\n",
2796  atxferloopdelay);
2797  ast_safe_sleep(transferee, atxferloopdelay);
2798  if (ast_check_hangup(transferee)) {
2799  ast_party_connected_line_free(&connected_line);
2800  return -1;
2801  }
2802  }
2803 
2804  /* Retry dialing party C. */
2805  ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
2806  newchan = feature_request_and_dial(transferer, transferer_name_orig,
2807  transferer, transferee, "Local",
2808  ast_best_codec(transferee->nativeformats), xferto,
2809  atxfernoanswertimeout, &outstate, transferer->language);
2810  ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
2811  !!newchan, outstate);
2812  if (newchan || ast_check_hangup(transferee)) {
2813  break;
2814  }
2815  }
2816  }
2817  ast_indicate(transferee, AST_CONTROL_UNHOLD);
2818  if (!newchan) {
2819  /* No party C or could not callback party B. */
2820  ast_party_connected_line_free(&connected_line);
2821  return -1;
2822  }
2823 
2824  /* newchan is up, we should prepare transferee and bridge them */
2825  if (ast_check_hangup(newchan)) {
2826  ast_hangup(newchan);
2827  ast_party_connected_line_free(&connected_line);
2828  return -1;
2829  }
2830  if (check_compat(transferee, newchan)) {
2831  ast_party_connected_line_free(&connected_line);
2832  return -1;
2833  }
2834  } else {
2835  /*
2836  * Both the transferer and transferee have hungup. If newchan
2837  * is up, hang it up as it has no one to talk to.
2838  */
2839  ast_debug(1, "Everyone is hungup.\n");
2840  if (newchan) {
2841  ast_hangup(newchan);
2842  }
2843  ast_party_connected_line_free(&connected_line);
2844  return -1;
2845  }
2846 
2847  /* Initiate the channel transfer of party A to party C (or recalled party B). */
2848  ast_cel_report_event(transferee, AST_CEL_ATTENDEDTRANSFER, NULL, NULL, newchan);
2849 
2850  xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", transferee->linkedid, 0, "Transfered/%s", transferee->name);
2851  if (!xferchan) {
2852  ast_hangup(newchan);
2853  ast_party_connected_line_free(&connected_line);
2854  return -1;
2855  }
2856 
2857  /* Give party A a momentary ringback tone during transfer. */
2859 
2860  /* Make formats okay */
2861  xferchan->readformat = transferee->readformat;
2862  xferchan->writeformat = transferee->writeformat;
2863 
2864  if (ast_channel_masquerade(xferchan, transferee)) {
2865  ast_hangup(xferchan);
2866  ast_hangup(newchan);
2867  ast_party_connected_line_free(&connected_line);
2868  return -1;
2869  }
2870 
2871  dash = strrchr(xferto, '@');
2872  if (dash) {
2873  /* Trim off the context. */
2874  *dash = '\0';
2875  }
2876  ast_explicit_goto(xferchan, transferer_real_context, xferto, 1);
2877  xferchan->_state = AST_STATE_UP;
2878  ast_clear_flag(xferchan, AST_FLAGS_ALL);
2879 
2880  /* Do the masquerade manually to make sure that is is completed. */
2881  ast_do_masquerade(xferchan);
2882 
2883  newchan->_state = AST_STATE_UP;
2884  ast_clear_flag(newchan, AST_FLAGS_ALL);
2885  tobj = ast_calloc(1, sizeof(*tobj));
2886  if (!tobj) {
2887  ast_hangup(xferchan);
2888  ast_hangup(newchan);
2889  ast_party_connected_line_free(&connected_line);
2890  return -1;
2891  }
2892 
2893  tobj->chan = newchan;
2894  tobj->peer = xferchan;
2895  tobj->bconfig = *config;
2896 
2897  ast_channel_lock(newchan);
2898  features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL);
2899  if (features_datastore && (dialfeatures = features_datastore->data)) {
2900  ast_copy_flags(&tobj->bconfig.features_callee, &dialfeatures->my_features,
2901  AST_FLAGS_ALL);
2902  }
2903  ast_channel_unlock(newchan);
2904 
2905  ast_channel_lock(xferchan);
2906  features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL);
2907  if (features_datastore && (dialfeatures = features_datastore->data)) {
2908  ast_copy_flags(&tobj->bconfig.features_caller, &dialfeatures->my_features,
2909  AST_FLAGS_ALL);
2910  }
2911  ast_channel_unlock(xferchan);
2912 
2914  tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
2915  }
2916 
2917  /*
2918  * xferchan is transferee, and newchan is the transfer target
2919  * So...in a transfer, who is the caller and who is the callee?
2920  *
2921  * When the call is originally made, it is clear who is caller and callee.
2922  * When a transfer occurs, it is my humble opinion that the transferee becomes
2923  * the caller, and the transfer target is the callee.
2924  *
2925  * The problem is that these macros were set with the intention of the original
2926  * caller and callee taking those roles. A transfer can totally mess things up,
2927  * to be technical. What sucks even more is that you can't effectively change
2928  * the macros in the dialplan during the call from the transferer to the transfer
2929  * target because the transferee is stuck with whatever role he originally had.
2930  *
2931  * I think the answer here is just to make sure that it is well documented that
2932  * during a transfer, the transferee is the "caller" and the transfer target
2933  * is the "callee."
2934  *
2935  * This means that if party B calls party A, and party B transfers party A to
2936  * party C, then A has switched roles for the call. Now party A will have the
2937  * caller macro called on his channel instead of the callee macro.
2938  *
2939  * Luckily, the method by which the party B to party C bridge is
2940  * launched above ensures that the transferee is the "chan" on
2941  * the bridge and the transfer target is the "peer," so my idea
2942  * for the roles post-transfer does not require extensive code
2943  * changes.
2944  */
2945 
2946  /* Transfer party C connected line to party A */
2947  ast_channel_lock(transferer);
2948  /*
2949  * Due to a limitation regarding when callerID is set on a Local channel,
2950  * we use the transferer's connected line information here.
2951  */
2952  ast_party_connected_line_copy(&connected_line, &transferer->connected);
2953  ast_channel_unlock(transferer);
2955  if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
2956  ast_channel_update_connected_line(xferchan, &connected_line, NULL);
2957  }
2958 
2959  /* Transfer party A connected line to party C */
2960  ast_channel_lock(xferchan);
2961  ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
2962  ast_channel_unlock(xferchan);
2964  if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
2965  ast_channel_update_connected_line(newchan, &connected_line, NULL);
2966  }
2967 
2968  if (ast_stream_and_wait(newchan, xfersound, ""))
2969  ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2971 
2972  ast_party_connected_line_free(&connected_line);
2973  return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
2974 }
2975 
2976 /* add atxfer and automon as undefined so you can only use em if you configure them */
2977 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
2978 
2980 
2982  { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2983  { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2984  { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2985  { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2986  { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2987  { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2988 };
2989 
2990 
2992 
2993 /*! \brief register new feature into feature_list*/
2995 {
2996  if (!feature) {
2997  ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
2998  return;
2999  }
3000 
3004 
3005  ast_verb(2, "Registered Feature '%s'\n",feature->sname);
3006 }
3007 
3008 /*!
3009  * \brief Add new feature group
3010  * \param fgname feature group name.
3011  *
3012  * Add new feature group to the feature group list insert at head of list.
3013  * \note This function MUST be called while feature_groups is locked.
3014  */
3015 static struct feature_group *register_group(const char *fgname)
3016 {
3017  struct feature_group *fg;
3018 
3019  if (!fgname) {
3020  ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
3021  return NULL;
3022  }
3023 
3024  if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
3025  return NULL;
3026  }
3027 
3028  ast_string_field_set(fg, gname, fgname);
3029 
3030  AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
3031 
3032  ast_verb(2, "Registered group '%s'\n", fg->gname);
3033 
3034  return fg;
3035 }
3036 
3037 /*!
3038  * \brief Add feature to group
3039  * \param fg feature group
3040  * \param exten
3041  * \param feature feature to add.
3042  *
3043  * Check fg and feature specified, add feature to list
3044  * \note This function MUST be called while feature_groups is locked.
3045  */
3046 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
3047 {
3048  struct feature_group_exten *fge;
3049 
3050  if (!fg) {
3051  ast_log(LOG_NOTICE, "You didn't pass a group!\n");
3052  return;
3053  }
3054 
3055  if (!feature) {
3056  ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
3057  return;
3058  }
3059 
3060  if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
3061  return;
3062  }
3063 
3064  ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
3065 
3066  fge->feature = feature;
3067 
3068  AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
3069 
3070  ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
3071  feature->sname, fg->gname, fge->exten);
3072 }
3073 
3075 {
3076  if (!feature) {
3077  return;
3078  }
3079 
3081  AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
3083 
3084  ast_free(feature);
3085 }
3086 
3087 /*! \brief Remove all features in the list */
3088 static void ast_unregister_features(void)
3089 {
3090  struct ast_call_feature *feature;
3091 
3093  while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
3094  ast_free(feature);
3095  }
3097 }
3098 
3099 /*! \brief find a call feature by name */
3100 static struct ast_call_feature *find_dynamic_feature(const char *name)
3101 {
3102  struct ast_call_feature *tmp;
3103 
3105  if (!strcasecmp(tmp->sname, name)) {
3106  break;
3107  }
3108  }
3109 
3110  return tmp;
3111 }
3112 
3113 /*! \brief Remove all feature groups in the list */
3114 static void ast_unregister_groups(void)
3115 {
3116  struct feature_group *fg;
3117  struct feature_group_exten *fge;
3118 
3120  while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
3121  while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
3123  ast_free(fge);
3124  }
3125 
3127  ast_free(fg);
3128  }
3130 }
3131 
3132 /*!
3133  * \brief Find a group by name
3134  * \param name feature name
3135  * \retval feature group on success.
3136  * \retval NULL on failure.
3137  */
3138 static struct feature_group *find_group(const char *name)
3139 {
3140  struct feature_group *fg = NULL;
3141 
3142  AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
3143  if (!strcasecmp(fg->gname, name))
3144  break;
3145  }
3146 
3147  return fg;
3148 }
3149 
3151 {
3153 }
3154 
3156 {
3158 }
3159 
3161 {
3162  int x;
3163  for (x = 0; x < FEATURES_COUNT; x++) {
3164  if (!strcasecmp(name, builtin_features[x].sname))
3165  return &builtin_features[x];
3166  }
3167  return NULL;
3168 }
3169 
3170 /*!
3171  * \brief exec an app by feature
3172  * \param chan,peer,config,code,sense,data
3173  *
3174  * Find a feature, determine which channel activated
3175  * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
3176  * \retval -1 error.
3177  * \retval -2 when an application cannot be found.
3178  */
3179 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
3180 {
3181  struct ast_app *app;
3182  struct ast_call_feature *feature = data;
3183  struct ast_channel *work, *idle;
3184  int res;
3185 
3186  if (!feature) { /* shouldn't ever happen! */
3187  ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
3188  return -1;
3189  }
3190 
3191  if (sense == FEATURE_SENSE_CHAN) {
3194  if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
3195  work = chan;
3196  idle = peer;
3197  } else {
3198  work = peer;
3199  idle = chan;
3200  }
3201  } else {
3204  if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
3205  work = peer;
3206  idle = chan;
3207  } else {
3208  work = chan;
3209  idle = peer;
3210  }
3211  }
3212 
3213  if (!(app = pbx_findapp(feature->app))) {
3214  ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
3215  return -2;
3216  }
3217 
3218  ast_autoservice_start(idle);
3220 
3221  pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", idle->name);
3222  pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", work->name);
3223  pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
3224  pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
3225 
3226  if (!ast_strlen_zero(feature->moh_class))
3227  ast_moh_start(idle, feature->moh_class, NULL);
3228 
3229  if (!strcasecmp("Gosub", feature->app)) {
3230  res = ast_app_exec_sub(NULL, work, feature->app_args, 0);
3231  } else if (!strcasecmp("Macro", feature->app)) {
3232  res = ast_app_exec_macro(NULL, work, feature->app_args);
3233  } else {
3234  res = pbx_exec(work, app, feature->app_args);
3235  }
3236 
3237  if (!ast_strlen_zero(feature->moh_class))
3238  ast_moh_stop(idle);
3239 
3240  ast_autoservice_stop(idle);
3241 
3242  if (res) {
3244  }
3245  return AST_FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
3246 }
3247 
3248 static void unmap_features(void)
3249 {
3250  int x;
3251 
3253  for (x = 0; x < FEATURES_COUNT; x++)
3254  strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
3256 }
3257 
3258 static int remap_feature(const char *name, const char *value)
3259 {
3260  int x, res = -1;
3261 
3263  for (x = 0; x < FEATURES_COUNT; x++) {
3264  if (strcasecmp(builtin_features[x].sname, name))
3265  continue;
3266 
3267  ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
3268  res = 0;
3269  break;
3270  }
3272 
3273  return res;
3274 }
3275 
3276 /*!
3277  * \brief Helper function for feature_interpret and ast_feature_detect
3278  * \param chan,peer,config,code,sense,dynamic_features_buf,features,operation,feature
3279  *
3280  * Lock features list, browse for code, unlock list
3281  * If a feature is found and the operation variable is set, that feature's
3282  * operation is executed. The first feature found is copied to the feature parameter.
3283  * \retval res on success.
3284  * \retval -1 on failure.
3285  */
3286 static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
3287  struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
3288  struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
3289 {
3290  int x;
3291  struct feature_group *fg = NULL;
3292  struct feature_group_exten *fge;
3293  struct ast_call_feature *tmpfeature;
3294  char *tmp, *tok;
3296  int feature_detected = 0;
3297 
3298  if (!(peer && chan && config) && operation == FEATURE_INTERPRET_DO) {
3299  return -1; /* can not run feature operation */
3300  }
3301 
3303  for (x = 0; x < FEATURES_COUNT; x++) {
3304  if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
3305  !ast_strlen_zero(builtin_features[x].exten)) {
3306  /* Feature is up for consideration */
3307  if (!strcmp(builtin_features[x].exten, code)) {
3308  ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
3309  if (operation == FEATURE_INTERPRET_CHECK) {
3310  res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
3311  } else if (operation == FEATURE_INTERPRET_DO) {
3312  res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
3313  }
3314  if (feature) {
3315  memcpy(feature, &builtin_features[x], sizeof(*feature));
3316  }
3317  feature_detected = 1;
3318  break;
3319  } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
3320  if (res == AST_FEATURE_RETURN_PASSDIGITS) {
3322  }
3323  }
3324  }
3325  }
3327 
3328  if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
3329  return res;
3330  }
3331 
3332  tmp = dynamic_features_buf;
3333 
3334  while ((tok = strsep(&tmp, "#"))) {
3336 
3337  fg = find_group(tok);
3338 
3339  if (fg) {
3340  AST_LIST_TRAVERSE(&fg->features, fge, entry) {
3341  if (!strcmp(fge->exten, code)) {
3342  if (operation) {
3343  res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
3344  }
3345  if (feature) {
3346  memcpy(feature, fge->feature, sizeof(*feature));
3347  }
3348  if (res != AST_FEATURE_RETURN_KEEPTRYING) {
3350  break;
3351  }
3353  } else if (!strncmp(fge->exten, code, strlen(code))) {
3355  }
3356  }
3357  if (fge) {
3358  break;
3359  }
3360  }
3361 
3363 
3365 
3366  if (!(tmpfeature = find_dynamic_feature(tok))) {
3368  continue;
3369  }
3370 
3371  /* Feature is up for consideration */
3372  if (!strcmp(tmpfeature->exten, code)) {
3373  ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
3374  if (operation == FEATURE_INTERPRET_CHECK) {
3375  res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
3376  } else if (operation == FEATURE_INTERPRET_DO) {
3377  res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
3378  }
3379  if (feature) {
3380  memcpy(feature, tmpfeature, sizeof(*feature));
3381  }
3382  if (res != AST_FEATURE_RETURN_KEEPTRYING) {
3384  break;
3385  }
3387  } else if (!strncmp(tmpfeature->exten, code, strlen(code)))
3389 
3391  }
3392 
3393  return res;
3394 }
3395 
3396 /*!
3397  * \brief Check the dynamic features
3398  * \param chan,peer,config,code,sense
3399  *
3400  * \retval res on success.
3401  * \retval -1 on failure.
3402  */
3403 static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense) {
3404 
3405  char dynamic_features_buf[128];
3406  const char *peer_dynamic_features, *chan_dynamic_features;
3407  struct ast_flags features;
3408  struct ast_call_feature feature;
3409  if (sense == FEATURE_SENSE_CHAN) {
3410  /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
3411  ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
3412  }
3413  else {
3414  /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
3415  ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
3416  }
3417 
3418  ast_channel_lock(peer);
3419  peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
3420  ast_channel_unlock(peer);
3421 
3422  ast_channel_lock(chan);
3423  chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
3424  ast_channel_unlock(chan);
3425 
3426  snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
3427 
3428  ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%u, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
3429 
3430  return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, FEATURE_INTERPRET_DO, &feature);
3431 }
3432 
3433 
3434 int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) {
3435 
3436  return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_DETECT, feature);
3437 }
3438 
3439 /*! \brief Check if a feature exists */
3440 static int feature_check(struct ast_channel *chan, struct ast_flags *features, char *code) {
3441  char *chan_dynamic_features;
3442  ast_channel_lock(chan);
3443  chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
3444  ast_channel_unlock(chan);
3445 
3446  return feature_interpret_helper(chan, NULL, NULL, code, 0, chan_dynamic_features, features, FEATURE_INTERPRET_CHECK, NULL);
3447 }
3448 
3449 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
3450 {
3451  int x;
3452 
3453  ast_clear_flag(config, AST_FLAGS_ALL);
3454 
3456  for (x = 0; x < FEATURES_COUNT; x++) {
3457  if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
3458  continue;
3459 
3460  if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
3462 
3463  if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
3465  }
3467 
3468  if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
3469  const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
3470 
3471  if (dynamic_features) {
3472  char *tmp = ast_strdupa(dynamic_features);
3473  char *tok;
3474  struct ast_call_feature *feature;
3475 
3476  /* while we have a feature */
3477  while ((tok = strsep(&tmp, "#"))) {
3478  struct feature_group *fg;
3479 
3481  AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
3482  struct feature_group_exten *fge;
3483 
3484  AST_LIST_TRAVERSE(&fg->features, fge, entry) {
3487  }
3490  }
3491  }
3492  }
3494 
3496  if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
3497  if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER)) {
3499  }
3500  if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE)) {
3502  }
3503  }
3505  }
3506  }
3507  }
3508 }
3509 
3510 /*!
3511  * \internal
3512  * \brief Get feature and dial.
3513  *
3514  * \param caller Channel to represent as the calling channel for the dialed channel.
3515  * \param caller_name Original caller channel name.
3516  * \param requestor Channel to say is requesting the dial (usually the caller).
3517  * \param transferee Channel that the dialed channel will be transferred to.
3518  * \param type Channel technology type to dial.
3519  * \param format Codec formats for dialed channel.
3520  * \param data Dialed channel extra parameters for ast_request() and ast_call().
3521  * \param timeout Time limit for dialed channel to answer in ms. Must be greater than zero.
3522  * \param outstate Status of dialed channel if unsuccessful.
3523  * \param language Language of the caller.
3524  *
3525  * \note
3526  * outstate can be:
3527  * 0, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION,
3528  * AST_CONTROL_ANSWER, or AST_CONTROL_UNHOLD. If
3529  * AST_CONTROL_UNHOLD then the caller channel cancelled the
3530  * transfer or the dialed channel did not answer before the
3531  * timeout.
3532  *
3533  * \details
3534  * Request channel, set channel variables, initiate call,
3535  * check if they want to disconnect, go into loop, check if timeout has elapsed,
3536  * check if person to be transferred hung up, check for answer break loop,
3537  * set cdr return channel.
3538  *
3539  * \retval Channel Connected channel for transfer.
3540  * \retval NULL on failure to get third party connected.
3541  *
3542  * \note This is similar to __ast_request_and_dial() in channel.c
3543  */
3545  const char *caller_name, struct ast_channel *requestor,
3546  struct ast_channel *transferee, const char *type, format_t format, void *data,
3547  int timeout, int *outstate, const char *language)
3548 {
3549  int state = 0;
3550  int cause = 0;
3551  int to;
3552  int caller_hungup;
3553  int transferee_hungup;
3554  struct ast_channel *chan;
3555  struct ast_channel *monitor_chans[3];
3556  struct ast_channel *active_channel;
3557  int res;
3558  int ready = 0;
3559  struct timeval started;
3560  int x, len = 0;
3561  char *disconnect_code = NULL, *dialed_code = NULL;
3562  struct ast_frame *f;
3563  AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
3564 
3565  caller_hungup = ast_check_hangup(caller);
3566 
3567  if (!(chan = ast_request(type, format, requestor, data, &cause))) {
3568  ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
3569  switch (cause) {
3570  case AST_CAUSE_BUSY:
3571  state = AST_CONTROL_BUSY;
3572  break;
3573  case AST_CAUSE_CONGESTION:
3574  state = AST_CONTROL_CONGESTION;
3575  break;
3576  default:
3577  state = 0;
3578  break;
3579  }
3580  goto done;
3581  }
3582 
3583  ast_string_field_set(chan, language, language);
3584  ast_channel_inherit_variables(caller, chan);
3585  pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller_name);
3586 
3587  ast_channel_lock(chan);
3589  ast_channel_unlock(chan);
3590 
3591  if (ast_call(chan, data, timeout)) {
3592  ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
3593  switch (chan->hangupcause) {
3594  case AST_CAUSE_BUSY:
3595  state = AST_CONTROL_BUSY;
3596  break;
3597  case AST_CAUSE_CONGESTION:
3598  state = AST_CONTROL_CONGESTION;
3599  break;
3600  default:
3601  state = 0;
3602  break;
3603  }
3604  goto done;
3605  }
3606 
3607  /* support dialing of the featuremap disconnect code while performing an attended tranfer */
3609  for (x = 0; x < FEATURES_COUNT; x++) {
3610  if (strcasecmp(builtin_features[x].sname, "disconnect"))
3611  continue;
3612 
3613  disconnect_code = builtin_features[x].exten;
3614  len = strlen(disconnect_code) + 1;
3615  dialed_code = ast_alloca(len);
3616  memset(dialed_code, 0, len);
3617  break;
3618  }
3620  x = 0;
3621  started = ast_tvnow();
3622  to = timeout;
3623  AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
3624 
3625  ast_poll_channel_add(caller, chan);
3626 
3627  transferee_hungup = 0;
3628  while (!ast_check_hangup(transferee) && (chan->_state != AST_STATE_UP)) {
3629  int num_chans = 0;
3630 
3631  monitor_chans[num_chans++] = transferee;
3632  monitor_chans[num_chans++] = chan;
3633  if (!caller_hungup) {
3634  if (ast_check_hangup(caller)) {
3635  caller_hungup = 1;
3636 
3637 #if defined(ATXFER_NULL_TECH)
3638  /* Change caller's name to ensure that it will remain unique. */
3639  set_new_chan_name(caller);
3640 
3641  /*
3642  * Get rid of caller's physical technology so it is free for
3643  * other calls.
3644  */
3645  set_kill_chan_tech(caller);
3646 #endif /* defined(ATXFER_NULL_TECH) */
3647  } else {
3648  /* caller is not hungup so monitor it. */
3649  monitor_chans[num_chans++] = caller;
3650  }
3651  }
3652 
3653  /* see if the timeout has been violated */
3654  if (ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
3655  state = AST_CONTROL_UNHOLD;
3656  ast_log(LOG_NOTICE, "We exceeded our AT-timeout for %s\n", chan->name);
3657  break; /*doh! timeout*/
3658  }
3659 
3660  active_channel = ast_waitfor_n(monitor_chans, num_chans, &to);
3661  if (!active_channel)
3662  continue;
3663 
3664  f = NULL;
3665  if (transferee == active_channel) {
3666  struct ast_frame *dup_f;
3667 
3668  f = ast_read(transferee);
3669  if (f == NULL) { /*doh! where'd he go?*/
3670  transferee_hungup = 1;
3671  state = 0;
3672  break;
3673  }
3674  if (ast_is_deferrable_frame(f)) {
3675  dup_f = ast_frisolate(f);
3676  if (dup_f) {
3677  if (dup_f == f) {
3678  f = NULL;
3679  }
3680  AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
3681  }
3682  }
3683  } else if (chan == active_channel) {
3684  if (!ast_strlen_zero(chan->call_forward)) {
3685  state = 0;
3686  ast_autoservice_start(transferee);
3687  chan = ast_call_forward(caller, chan, NULL, format, NULL, &state);
3688  ast_autoservice_stop(transferee);
3689  if (!chan) {
3690  break;
3691  }
3692  continue;
3693  }
3694  f = ast_read(chan);
3695  if (f == NULL) { /*doh! where'd he go?*/
3696  switch (chan->hangupcause) {
3697  case AST_CAUSE_BUSY:
3698  state = AST_CONTROL_BUSY;
3699  break;
3700  case AST_CAUSE_CONGESTION:
3701  state = AST_CONTROL_CONGESTION;
3702  break;
3703  default:
3704  state = 0;
3705  break;
3706  }
3707  break;
3708  }
3709 
3710  if (f->frametype == AST_FRAME_CONTROL) {
3711  if (f->subclass.integer == AST_CONTROL_RINGING) {
3712  ast_verb(3, "%s is ringing\n", chan->name);
3714  } else if (f->subclass.integer == AST_CONTROL_BUSY) {
3715  state = f->subclass.integer;
3716  ast_verb(3, "%s is busy\n", chan->name);
3717  ast_indicate(caller, AST_CONTROL_BUSY);
3718  ast_frfree(f);
3719  break;
3720  } else if (f->subclass.integer == AST_CONTROL_INCOMPLETE) {
3721  ast_verb(3, "%s dialed incomplete extension %s; ignoring\n", chan->name, chan->exten);
3722  } else if (f->subclass.integer == AST_CONTROL_CONGESTION) {
3723  state = f->subclass.integer;
3724  ast_verb(3, "%s is congested\n", chan->name);
3726  ast_frfree(f);
3727  break;
3728  } else if (f->subclass.integer == AST_CONTROL_ANSWER) {
3729  /* This is what we are hoping for */
3730  state = f->subclass.integer;
3731  ast_frfree(f);
3732  ready=1;
3733  break;
3734  } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
3735  if (caller_hungup) {
3736  struct ast_party_connected_line connected;
3737 
3738  /* Just save it for the transfer. */
3739  ast_party_connected_line_set_init(&connected, &caller->connected);
3741  &connected);
3742  if (!res) {
3743  ast_channel_set_connected_line(caller, &connected, NULL);
3744  }
3745  ast_party_connected_line_free(&connected);
3746  } else {
3747  ast_autoservice_start(transferee);
3748  if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
3750  f->data.ptr, f->datalen);
3751  }
3752  ast_autoservice_stop(transferee);
3753  }
3754  } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
3755  if (!caller_hungup) {
3756  ast_autoservice_start(transferee);
3757  if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
3759  f->data.ptr, f->datalen);
3760  }
3761  ast_autoservice_stop(transferee);
3762  }
3763  } else if (f->subclass.integer != -1
3766  ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer);
3767  }
3768  /* else who cares */
3769  } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
3770  ast_write(caller, f);
3771  }
3772  } else if (caller == active_channel) {
3773  f = ast_read(caller);
3774  if (f) {
3775  if (f->frametype == AST_FRAME_DTMF) {
3776  dialed_code[x++] = f->subclass.integer;
3777  dialed_code[x] = '\0';
3778  if (strlen(dialed_code) == len) {
3779  x = 0;
3780  } else if (x && strncmp(dialed_code, disconnect_code, x)) {
3781  x = 0;
3782  dialed_code[x] = '\0';
3783  }
3784  if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
3785  /* Caller Canceled the call */
3786  state = AST_CONTROL_UNHOLD;
3787  ast_frfree(f);
3788  break;
3789  }
3790  } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
3791  ast_write(chan, f);
3792  }
3793  }
3794  }
3795  if (f)
3796  ast_frfree(f);
3797  } /* end while */
3798 
3799  ast_poll_channel_del(caller, chan);
3800 
3801  /*
3802  * We need to free all the deferred frames, but we only need to
3803  * queue the deferred frames if no hangup was received.
3804  */
3805  ast_channel_lock(transferee);
3806  transferee_hungup = (transferee_hungup || ast_check_hangup(transferee));
3807  while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
3808  if (!transferee_hungup) {
3809  ast_queue_frame_head(transferee, f);
3810  }
3811  ast_frfree(f);
3812  }
3813  ast_channel_unlock(transferee);
3814 
3815 done:
3816  ast_indicate(caller, -1);
3817  if (chan && (ready || chan->_state == AST_STATE_UP)) {
3818  state = AST_CONTROL_ANSWER;
3819  } else if (chan) {
3820  ast_hangup(chan);
3821  chan = NULL;
3822  }
3823 
3824  if (outstate)
3825  *outstate = state;
3826 
3827  return chan;
3828 }
3829 
3830 void ast_channel_log(char *title, struct ast_channel *chan);
3831 
3832 void ast_channel_log(char *title, struct ast_channel *chan) /* for debug, this is handy enough to justify keeping it in the source */
3833 {
3834  ast_log(LOG_NOTICE, "______ %s (%lx)______\n", title, (unsigned long)chan);
3835  ast_log(LOG_NOTICE, "CHAN: name: %s; appl: %s; data: %s; contxt: %s; exten: %s; pri: %d;\n",
3836  chan->name, chan->appl, chan->data, chan->context, chan->exten, chan->priority);
3837  ast_log(LOG_NOTICE, "CHAN: acctcode: %s; dialcontext: %s; amaflags: %x; maccontxt: %s; macexten: %s; macpri: %d;\n",
3838  chan->accountcode, chan->dialcontext, (unsigned)chan->amaflags, chan->macrocontext, chan->macroexten, chan->macropriority);
3839  ast_log(LOG_NOTICE, "CHAN: masq: %p; masqr: %p; _bridge: %p; uniqueID: %s; linkedID:%s\n",
3840  chan->masq, chan->masqr,
3841  chan->_bridge, chan->uniqueid, chan->linkedid);
3842  if (chan->masqr)
3843  ast_log(LOG_NOTICE, "CHAN: masquerading as: %s; cdr: %p;\n",
3844  chan->masqr->name, chan->masqr->cdr);
3845  if (chan->_bridge)
3846  ast_log(LOG_NOTICE, "CHAN: Bridged to %s\n", chan->_bridge->name);
3847 
3848  ast_log(LOG_NOTICE, "===== done ====\n");
3849 }
3850 
3851 /*!
3852  * \brief return the first unlocked cdr in a possible chain
3853  */
3854 static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
3855 {
3856  struct ast_cdr *cdr_orig = cdr;
3857  while (cdr) {
3859  return cdr;
3860  cdr = cdr->next;
3861  }
3862  return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
3863 }
3864 
3865 static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
3866 {
3867  const char *feature;
3868 
3869  if (ast_strlen_zero(features)) {
3870  return;
3871  }
3872 
3873  for (feature = features; *feature; feature++) {
3874  switch (*feature) {
3875  case 'T' :
3876  case 't' :
3878  break;
3879  case 'K' :
3880  case 'k' :
3882  break;
3883  case 'H' :
3884  case 'h' :
3886  break;
3887  case 'W' :
3888  case 'w' :
3890  break;
3891  default :
3892  ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
3893  }
3894  }
3895 }
3896 
3897 static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
3898 {
3899  if (add_features_datastore(caller, &config->features_caller, &config->features_callee)) {
3900  /*
3901  * If we don't return here, then when we do a builtin_atxfer we
3902  * will copy the disconnect flags over from the atxfer to the
3903  * callee (Party C).
3904  */
3905  return;
3906  }
3907 
3908  add_features_datastore(callee, &config->features_callee, &config->features_caller);
3909 }
3910 
3911 static void clear_dialed_interfaces(struct ast_channel *chan)
3912 {
3913  struct ast_datastore *di_datastore;
3914 
3915  ast_channel_lock(chan);
3916  if ((di_datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL))) {
3917  if (option_debug) {
3918  ast_log(LOG_DEBUG, "Removing dialed interfaces datastore on %s since we're bridging\n", chan->name);
3919  }
3920  if (!ast_channel_datastore_remove(chan, di_datastore)) {
3921  ast_datastore_free(di_datastore);
3922  }
3923  }
3924  ast_channel_unlock(chan);
3925 }
3926 
3927 void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
3928 {
3929  int dead;
3930  long duration;
3931 
3932  ast_channel_lock(chan);
3933  dead = ast_test_flag(chan, AST_FLAG_ZOMBIE)
3934  || (chan->_softhangup
3936  ast_channel_unlock(chan);
3937  if (dead) {
3938  /* Channel is a zombie or a real hangup. */
3939  return;
3940  }
3941 
3942  duration = ast_tvdiff_ms(ast_tvnow(), start);
3943  ast_senddigit_end(chan, digit, duration);
3944  ast_log(LOG_DTMF, "DTMF end '%c' simulated on %s due to %s, duration %ld ms\n",
3945  digit, chan->name, why, duration);
3946 }
3947 
3948 /*!
3949  * \brief bridge the call and set CDR
3950  *
3951  * \param chan The bridge considers this channel the caller.
3952  * \param peer The bridge considers this channel the callee.
3953  * \param config Configuration for this bridge.
3954  *
3955  * Set start time, check for two channels,check if monitor on
3956  * check for feature activation, create new CDR
3957  * \retval res on success.
3958  * \retval -1 on failure to bridge.
3959  */
3960 int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
3961 {
3962  /* Copy voice back and forth between the two channels. Give the peer
3963  the ability to transfer calls with '#<extension' syntax. */
3964  struct ast_frame *f;
3965  struct ast_channel *who;
3966  char chan_featurecode[FEATURE_MAX_LEN + 1]="";
3967  char peer_featurecode[FEATURE_MAX_LEN + 1]="";
3968  char orig_channame[AST_CHANNEL_NAME];
3969  char orig_peername[AST_CHANNEL_NAME];
3970  int res;
3971  int diff;
3972  int hasfeatures=0;
3973  int hadfeatures=0;
3974  int autoloopflag;
3975  int sendingdtmfdigit = 0;
3976  int we_disabled_peer_cdr = 0;
3977  struct ast_option_header *aoh;
3978  struct ast_cdr *bridge_cdr = NULL;
3979  struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */
3980  struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */
3981  struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
3982  struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
3983  struct ast_silence_generator *silgen = NULL;
3984  const char *h_context;
3985 
3986  pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
3987  pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
3988 
3989  /* Clear any BLINDTRANSFER since the transfer has completed. */
3990  pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
3991  pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", NULL);
3992 
3993  set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
3994  add_features_datastores(chan, peer, config);
3995 
3996  /* This is an interesting case. One example is if a ringing channel gets redirected to
3997  * an extension that picks up a parked call. This will make sure that the call taken
3998  * out of parking gets told that the channel it just got bridged to is still ringing. */
4001  }
4002 
4003  if (monitor_ok) {
4004  const char *monitor_exec;
4005  struct ast_channel *src = NULL;
4006  if (!monitor_app) {
4007  if (!(monitor_app = pbx_findapp("Monitor")))
4008  monitor_ok=0;
4009  }
4010  if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
4011  src = chan;
4012  else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
4013  src = peer;
4014  if (monitor_app && src) {
4015  char *tmp = ast_strdupa(monitor_exec);
4016  pbx_exec(src, monitor_app, tmp);
4017  }
4018  }
4019 
4020  set_config_flags(chan, peer, config);
4021 
4022  /* Answer if need be */
4023  if (chan->_state != AST_STATE_UP) {
4024  if (ast_raw_answer(chan, 1)) {
4025  return -1;
4026  }
4027  }
4028 
4029 #ifdef FOR_DEBUG
4030  /* show the two channels and cdrs involved in the bridge for debug & devel purposes */
4031  ast_channel_log("Pre-bridge CHAN Channel info", chan);
4032  ast_channel_log("Pre-bridge PEER Channel info", peer);
4033 #endif
4034  /* two channels are being marked as linked here */
4035  ast_channel_set_linkgroup(chan,peer);
4036 
4037  /* copy the userfield from the B-leg to A-leg if applicable */
4038  if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
4039  char tmp[256];
4040 
4041  ast_channel_lock(chan);
4042  if (!ast_strlen_zero(chan->cdr->userfield)) {
4043  snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
4044  ast_cdr_appenduserfield(chan, tmp);
4045  } else {
4046  ast_cdr_setuserfield(chan, peer->cdr->userfield);
4047  }
4048  ast_channel_unlock(chan);
4049  /* Don't delete the CDR; just disable it. */
4051  we_disabled_peer_cdr = 1;
4052  }
4053  ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
4054  ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
4055 
4056  if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
4057  ast_channel_lock_both(chan, peer);
4058  if (chan_cdr) {
4059  ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
4060  ast_cdr_update(chan);
4061  bridge_cdr = ast_cdr_dup_unique_swap(chan_cdr);
4062  /* rip any forked CDR's off of the chan_cdr and attach
4063  * them to the bridge_cdr instead */
4064  bridge_cdr->next = chan_cdr->next;
4065  chan_cdr->next = NULL;
4066  ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
4067  ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
4068  if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) {
4069  ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
4070  }
4071  ast_cdr_setaccount(peer, chan->accountcode);
4072  } else {
4073  /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
4074  bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
4075  ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
4076  ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
4077  ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
4078  ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
4079  ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
4080  ast_cdr_setcid(bridge_cdr, chan);
4081  bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL;
4082  bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags;
4083  ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
4084  /* Destination information */
4085  ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
4086  ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
4087  if (peer_cdr) {
4088  bridge_cdr->start = peer_cdr->start;
4089  ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
4090  } else {
4091  ast_cdr_start(bridge_cdr);
4092  }
4093  }
4094  ast_channel_unlock(chan);
4095  ast_channel_unlock(peer);
4096 
4097  ast_debug(4,"bridge answer set, chan answer set\n");
4098  /* peer_cdr->answer will be set when a macro runs on the peer;
4099  in that case, the bridge answer will be delayed while the
4100  macro plays on the peer channel. The peer answered the call
4101  before the macro started playing. To the phone system,
4102  this is billable time for the call, even tho the caller
4103  hears nothing but ringing while the macro does its thing. */
4104 
4105  /* Another case where the peer cdr's time will be set, is when
4106  A self-parks by pickup up phone and dialing 700, then B
4107  picks up A by dialing its parking slot; there may be more
4108  practical paths that get the same result, tho... in which
4109  case you get the previous answer time from the Park... which
4110  is before the bridge's start time, so I added in the
4111  tvcmp check to the if below */
4112 
4113  if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) {
4114  ast_cdr_setanswer(bridge_cdr, peer_cdr->answer);
4115  ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition);
4116  if (chan_cdr) {
4117  ast_cdr_setanswer(chan_cdr, peer_cdr->answer);
4118  ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition);
4119  }
4120  } else {
4121  ast_cdr_answer(bridge_cdr);
4122  if (chan_cdr) {
4123  ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
4124  }
4125  }
4126  if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
4127  if (chan_cdr) {
4129  }
4130  if (peer_cdr) {
4132  }
4133  }
4134  /* the DIALED flag may be set if a dialed channel is transferred
4135  * and then bridged to another channel. In order for the
4136  * bridge CDR to be written, the DIALED flag must not be
4137  * present. */
4138  ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED);
4139  }
4140  ast_cel_report_event(chan, AST_CEL_BRIDGE_START, NULL, NULL, peer);
4141 
4142  /* If we are bridging a call, stop worrying about forwarding loops. We presume that if
4143  * a call is being bridged, that the humans in charge know what they're doing. If they
4144  * don't, well, what can we do about that? */
4147 
4148  for (;;) {
4149  struct ast_channel *other; /* used later */
4150 
4151  res = ast_channel_bridge(chan, peer, config, &f, &who);
4152 
4153  if (ast_test_flag(chan, AST_FLAG_ZOMBIE)
4154  || ast_test_flag(peer, AST_FLAG_ZOMBIE)) {
4155  /* Zombies are present time to leave! */
4156  res = -1;
4157  if (f) {
4158  ast_frfree(f);
4159  }
4160  goto before_you_go;
4161  }
4162 
4163  /* When frame is not set, we are probably involved in a situation
4164  where we've timed out.
4165  When frame is set, we'll come this code twice; once for DTMF_BEGIN
4166  and also for DTMF_END. If we flow into the following 'if' for both, then
4167  our wait times are cut in half, as both will subtract from the
4168  feature_timer. Not good!
4169  */
4170  if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
4171  /* Update feature timer for next pass */
4172  diff = ast_tvdiff_ms(ast_tvnow(), config->feature_start_time);
4173  if (res == AST_BRIDGE_RETRY) {
4174  /* The feature fully timed out but has not been updated. Skip
4175  * the potential round error from the diff calculation and
4176  * explicitly set to expired. */
4177  config->feature_timer = -1;
4178  } else {
4179  config->feature_timer -= diff;
4180  }
4181 
4182  if (hasfeatures) {
4183  if (config->feature_timer <= 0) {
4184  /* Not *really* out of time, just out of time for
4185  digits to come in for features. */
4186  ast_debug(1, "Timed out for feature!\n");
4187  if (!ast_strlen_zero(peer_featurecode)) {
4188  ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
4189  memset(peer_featurecode, 0, sizeof(peer_featurecode));
4190  }
4191  if (!ast_strlen_zero(chan_featurecode)) {
4192  ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
4193  memset(chan_featurecode, 0, sizeof(chan_featurecode));
4194  }
4195  if (f)
4196  ast_frfree(f);
4197  hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
4198  if (!hasfeatures) {
4199  /* No more digits expected - reset the timer */
4200  config->feature_timer = 0;
4201  }
4202  hadfeatures = hasfeatures;
4203  /* Continue as we were */
4204  continue;
4205  } else if (!f) {
4206  /* The bridge returned without a frame and there is a feature in progress.
4207  * However, we don't think the feature has quite yet timed out, so just
4208  * go back into the bridge. */
4209  continue;
4210  }
4211  } else {
4212  if (config->feature_timer <=0) {
4213  /* We ran out of time */
4214  config->feature_timer = 0;
4215  who = chan;
4216  if (f)
4217  ast_frfree(f);
4218  f = NULL;
4219  res = 0;
4220  }
4221  }
4222  }
4223  if (res < 0) {
4224  if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) {
4225  ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
4226  }
4227  goto before_you_go;
4228  }
4229 
4230  if (!f || (f->frametype == AST_FRAME_CONTROL &&
4233  res = -1;
4234  break;
4235  }
4236  /* many things should be sent to the 'other' channel */
4237  other = (who == chan) ? peer : chan;
4238  if (f->frametype == AST_FRAME_CONTROL) {
4239  switch (f->subclass.integer) {
4240  case AST_CONTROL_RINGING:
4241  case AST_CONTROL_FLASH:
4242  case -1:
4243  ast_indicate(other, f->subclass.integer);
4244  break;
4246  if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
4247  break;
4248  }
4249  ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
4250  break;
4252  if (!ast_channel_redirecting_macro(who, other, f, who != chan, 1)) {
4253  break;
4254  }
4255  ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
4256  break;
4257  case AST_CONTROL_AOC:
4258  case AST_CONTROL_HOLD:
4259  case AST_CONTROL_UNHOLD:
4260  ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
4261  break;
4262  case AST_CONTROL_OPTION:
4263  aoh = f->data.ptr;
4264  /* Forward option Requests, but only ones we know are safe
4265  * These are ONLY sent by chan_iax2 and I'm not convinced that
4266  * they are useful. I haven't deleted them entirely because I
4267  * just am not sure of the ramifications of removing them. */
4268  if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
4269  switch (ntohs(aoh->option)) {
4271  case AST_OPTION_TDD:
4272  case AST_OPTION_RELAXDTMF:
4273  case AST_OPTION_AUDIO_MODE:
4275  case AST_OPTION_FAX_DETECT:
4276  ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
4277  f->datalen - sizeof(struct ast_option_header), 0);
4278  }
4279  }
4280  break;
4281  }
4282  } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
4283  struct ast_flags *cfg;
4284  char dtmfcode[2] = { f->subclass.integer, };
4285  size_t featurelen;
4286 
4287  if (who == chan) {
4288  featurelen = strlen(chan_featurecode);
4289  cfg = &(config->features_caller);
4290  } else {
4291  featurelen = strlen(peer_featurecode);
4292  cfg = &(config->features_callee);
4293  }
4294  /* Take a peek if this (possibly) matches a feature. If not, just pass this
4295  * DTMF along untouched. If this is not the first digit of a multi-digit code
4296  * then we need to fall through and stream the characters if it matches */
4297  if (featurelen == 0
4298  && feature_check(chan, cfg, &dtmfcode[0]) == AST_FEATURE_RETURN_PASSDIGITS) {
4299  if (option_debug > 3) {
4300  ast_log(LOG_DEBUG, "Passing DTMF through, since it is not a feature code\n");
4301  }
4302  ast_write(other, f);
4303  sendingdtmfdigit = 1;
4304  } else {
4305  /* If ast_opt_transmit_silence is set, then we need to make sure we are
4306  * transmitting something while we hold on to the DTMF waiting for a
4307  * feature. */
4308  if (!silgen && ast_opt_transmit_silence) {
4309  silgen = ast_channel_start_silence_generator(other);
4310  }
4311  if (option_debug > 3) {
4312  ast_log(LOG_DEBUG, "Not passing DTMF through, since it may be a feature code\n");
4313  }
4314  }
4315  } else if (f->frametype == AST_FRAME_DTMF_END) {
4316  char *featurecode;
4317  int sense;
4318 
4319  hadfeatures = hasfeatures;
4320  /* This cannot overrun because the longest feature is one shorter than our buffer */
4321  if (who == chan) {
4322  sense = FEATURE_SENSE_CHAN;
4323  featurecode = chan_featurecode;
4324  } else {
4325  sense = FEATURE_SENSE_PEER;
4326  featurecode = peer_featurecode;
4327  }
4328 
4329  if (sendingdtmfdigit == 1) {
4330  /* We let the BEGIN go through happily, so let's not bother with the END,
4331  * since we already know it's not something we bother with */
4332  ast_write(other, f);
4333  sendingdtmfdigit = 0;
4334  } else {
4335  /*! append the event to featurecode. we rely on the string being zero-filled, and
4336  * not overflowing it.
4337  * \todo XXX how do we guarantee the latter ?
4338  */
4339  featurecode[strlen(featurecode)] = f->subclass.integer;
4340  /* Get rid of the frame before we start doing "stuff" with the channels */
4341  ast_frfree(f);
4342  f = NULL;
4343  if (silgen) {
4344  ast_channel_stop_silence_generator(other, silgen);
4345  silgen = NULL;
4346  }
4347  config->feature_timer = 0;
4348  res = feature_interpret(chan, peer, config, featurecode, sense);
4349  switch(res) {
4351  ast_dtmf_stream(other, who, featurecode, 0, 0);
4352  /* Fall through */
4354  memset(featurecode, 0, sizeof(chan_featurecode));
4355  break;
4356  }
4357  if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
4358  res = 0;
4359  } else {
4360  break;
4361  }
4362  hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
4363  if (hadfeatures && !hasfeatures) {
4364  /* Feature completed or timed out */
4365  config->feature_timer = 0;
4366  } else if (hasfeatures) {
4367  if (config->timelimit) {
4368  /* No warning next time - we are waiting for feature code */
4370  }
4371  config->feature_start_time = ast_tvnow();
4373  ast_debug(1, "Set feature timer to %ld ms\n", config->feature_timer);
4374  }
4375  }
4376  }
4377  if (f)
4378  ast_frfree(f);
4379  }
4380  ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, peer);
4381 
4382 before_you_go:
4383  if (chan->sending_dtmf_digit) {
4385  "bridge end");
4386  }
4387  if (peer->sending_dtmf_digit) {
4389  "bridge end");
4390  }
4391 
4392  /* Just in case something weird happened and we didn't clean up the silence generator... */
4393  if (silgen) {
4394  ast_channel_stop_silence_generator(who == chan ? peer : chan, silgen);
4395  silgen = NULL;
4396  }
4397 
4398  /* Wait for any dual redirect to complete. */
4400  sched_yield();
4401  }
4402 
4404  ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */
4405  if (bridge_cdr) {
4406  ast_cdr_discard(bridge_cdr);
4407  /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */
4408  }
4409  return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */
4410  }
4411 
4412  if (config->end_bridge_callback) {
4414  }
4415 
4416  /* run the hangup exten on the chan object IFF it was NOT involved in a parking situation
4417  * if it were, then chan belongs to a different thread now, and might have been hung up long
4418  * ago.
4419  */
4421  /*
4422  * If the bridge was broken for a hangup that isn't real,
4423  * then don't run the h extension, because the channel isn't
4424  * really hung up. This should really only happen with AST_SOFTHANGUP_ASYNCGOTO,
4425  * but it doesn't hurt to check AST_SOFTHANGUP_UNBRIDGE either.
4426  */
4427  h_context = NULL;
4428  } else if (ast_test_flag(&config->features_caller, AST_FEATURE_NO_H_EXTEN)) {
4429  h_context = NULL;
4430  } else if (ast_exists_extension(chan, chan->context, "h", 1,
4431  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
4432  h_context = chan->context;
4433  } else if (!ast_strlen_zero(chan->macrocontext)
4434  && ast_exists_extension(chan, chan->macrocontext, "h", 1,
4435  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
4436  h_context = chan->macrocontext;
4437  } else {
4438  h_context = NULL;
4439  }
4440  if (h_context) {
4441  struct ast_cdr *swapper = NULL;
4442  char savelastapp[AST_MAX_EXTENSION];
4443  char savelastdata[AST_MAX_EXTENSION];
4444  char save_context[AST_MAX_CONTEXT];
4445  char save_exten[AST_MAX_EXTENSION];
4446  int save_prio;
4447  int found = 0; /* set if we find at least one match */
4448  int spawn_error = 0;
4449 
4450  /*
4451  * Make sure that the channel is marked as hungup since we are
4452  * going to run the "h" exten on it.
4453  */
4455 
4456  autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
4458  if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
4459  ast_cdr_end(bridge_cdr);
4460  }
4461 
4462  /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
4463  dialplan code operate on it */
4464  ast_channel_lock(chan);
4465  if (bridge_cdr) {
4466  swapper = chan->cdr;
4467  ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
4468  ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
4469  chan->cdr = bridge_cdr;
4470  }
4471  ast_copy_string(save_context, chan->context, sizeof(save_context));
4472  ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
4473  save_prio = chan->priority;
4474  if (h_context != chan->context) {
4475  ast_copy_string(chan->context, h_context, sizeof(chan->context));
4476  }
4477  ast_copy_string(chan->exten, "h", sizeof(chan->exten));
4478  chan->priority = 1;
4479  ast_channel_unlock(chan);
4480 
4481  while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten,
4482  chan->priority,
4483  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
4484  &found, 1)) == 0) {
4485  chan->priority++;
4486  }
4487  if (found && spawn_error) {
4488  /* Something bad happened, or a hangup has been requested. */
4489  ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
4490  ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
4491  }
4492 
4493  /* swap it back */
4494  ast_channel_lock(chan);
4495  ast_copy_string(chan->context, save_context, sizeof(chan->context));
4496  ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
4497  chan->priority = save_prio;
4498  if (bridge_cdr) {
4499  if (chan->cdr == bridge_cdr) {
4500  chan->cdr = swapper;
4501  } else {
4502  bridge_cdr = NULL;
4503  }
4504  }
4505  /* An "h" exten has been run, so indicate that one has been run. */
4507  ast_channel_unlock(chan);
4508 
4509  /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
4510  if (bridge_cdr) {
4511  ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
4512  ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
4513  }
4514  ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
4515  }
4516 
4517  /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
4518  new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
4519  /* If the channel CDR has been modified during the call, record the changes in the bridge cdr,
4520  * BUT, if we've gone through the h extension block above, the CDR got swapped so don't overwrite
4521  * what was done in the h extension. What a mess. This is why you never touch CDR code. */
4522  if (new_chan_cdr && bridge_cdr && !h_context) {
4523  ast_cdr_copy_vars(bridge_cdr, new_chan_cdr);
4524  ast_copy_string(bridge_cdr->userfield, new_chan_cdr->userfield, sizeof(bridge_cdr->userfield));
4525  bridge_cdr->amaflags = new_chan_cdr->amaflags;
4526  ast_copy_string(bridge_cdr->accountcode, new_chan_cdr->accountcode, sizeof(bridge_cdr->accountcode));
4527  if (ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) {
4529  }
4530  }
4531 
4532  /* we can post the bridge CDR at this point */
4533  if (bridge_cdr) {
4534  ast_cdr_end(bridge_cdr);
4535  ast_cdr_detach(bridge_cdr);
4536  }
4537 
4538  /* do a specialized reset on the beginning channel
4539  CDR's, if they still exist, so as not to mess up
4540  issues in future bridges;
4541 
4542  Here are the rules of the game:
4543  1. The chan and peer channel pointers will not change
4544  during the life of the bridge.
4545  2. But, in transfers, the channel names will change.
4546  between the time the bridge is started, and the
4547  time the channel ends.
4548  Usually, when a channel changes names, it will
4549  also change CDR pointers.
4550  3. Usually, only one of the two channels (chan or peer)
4551  will change names.
4552  4. Usually, if a channel changes names during a bridge,
4553  it is because of a transfer. Usually, in these situations,
4554  it is normal to see 2 bridges running simultaneously, and
4555  it is not unusual to see the two channels that change
4556  swapped between bridges.
4557  5. After a bridge occurs, we have 2 or 3 channels' CDRs
4558  to attend to; if the chan or peer changed names,
4559  we have the before and after attached CDR's.
4560  */
4561 
4562  if (new_chan_cdr) {
4563  struct ast_channel *chan_ptr = NULL;
4564 
4565  if (strcasecmp(orig_channame, chan->name) != 0) {
4566  /* old channel */
4567  if ((chan_ptr = ast_channel_get_by_name(orig_channame))) {
4568  ast_channel_lock(chan_ptr);
4569  if (!ast_bridged_channel(chan_ptr)) {
4570  struct ast_cdr *cur;
4571  for (cur = chan_ptr->cdr; cur; cur = cur->next) {
4572  if (cur == chan_cdr) {
4573  break;
4574  }
4575  }
4576  if (cur) {
4577  ast_cdr_specialized_reset(chan_cdr, 0);
4578  }
4579  }
4580  ast_channel_unlock(chan_ptr);
4581  chan_ptr = ast_channel_unref(chan_ptr);
4582  }
4583  /* new channel */
4584  ast_cdr_specialized_reset(new_chan_cdr, 0);
4585  } else {
4586  ast_cdr_specialized_reset(chan->cdr, 0); /* nothing changed, reset the chan cdr */
4587  }
4588  }
4589 
4590  {
4591  struct ast_channel *chan_ptr = NULL;
4592  new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
4593  if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED))
4594  ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
4595  if (strcasecmp(orig_peername, peer->name) != 0) {
4596  /* old channel */
4597  if ((chan_ptr = ast_channel_get_by_name(orig_peername))) {
4598  ast_channel_lock(chan_ptr);
4599  if (!ast_bridged_channel(chan_ptr)) {
4600  struct ast_cdr *cur;
4601  for (cur = chan_ptr->cdr; cur; cur = cur->next) {
4602  if (cur == peer_cdr) {
4603  break;
4604  }
4605  }
4606  if (cur) {
4607  ast_cdr_specialized_reset(peer_cdr, 0);
4608  }
4609  }
4610  ast_channel_unlock(chan_ptr);
4611  chan_ptr = ast_channel_unref(chan_ptr);
4612  }
4613  /* new channel */
4614  if (new_peer_cdr) {
4615  ast_cdr_specialized_reset(new_peer_cdr, 0);
4616  }
4617  } else {
4618  if (we_disabled_peer_cdr) {
4620  }
4621  ast_cdr_specialized_reset(peer->cdr, 0); /* nothing changed, reset the peer cdr */
4622  }
4623  }
4624 
4625  return res;
4626 }
4627 
4628 /*! \brief Output parking event to manager */
4629 static void post_manager_event(const char *s, struct parkeduser *pu)
4630 {
4632  "Exten: %s\r\n"
4633  "Channel: %s\r\n"
4634  "Parkinglot: %s\r\n"
4635  "CallerIDNum: %s\r\n"
4636  "CallerIDName: %s\r\n"
4637  "ConnectedLineNum: %s\r\n"
4638  "ConnectedLineName: %s\r\n"
4639  "UniqueID: %s\r\n",
4640  pu->parkingexten,
4641  pu->chan->name,
4642  pu->parkinglot->name,
4643  S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
4644  S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
4645  S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
4646  S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
4647  pu->chan->uniqueid
4648  );
4649 }
4650 
4651 static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
4652 {
4653  int i = 0;
4654  enum {
4655  OPT_CALLEE_REDIRECT = 't',
4656  OPT_CALLER_REDIRECT = 'T',
4657  OPT_CALLEE_AUTOMON = 'w',
4658  OPT_CALLER_AUTOMON = 'W',
4659  OPT_CALLEE_DISCONNECT = 'h',
4660  OPT_CALLER_DISCONNECT = 'H',
4661  OPT_CALLEE_PARKCALL = 'k',
4662  OPT_CALLER_PARKCALL = 'K',
4663  };
4664 
4665  memset(options, 0, len);
4666  if (ast_test_flag(features_caller, AST_FEATURE_REDIRECT) && i < len) {
4667  options[i++] = OPT_CALLER_REDIRECT;
4668  }
4669  if (ast_test_flag(features_caller, AST_FEATURE_AUTOMON) && i < len) {
4670  options[i++] = OPT_CALLER_AUTOMON;
4671  }
4672  if (ast_test_flag(features_caller, AST_FEATURE_DISCONNECT) && i < len) {
4673  options[i++] = OPT_CALLER_DISCONNECT;
4674  }
4675  if (ast_test_flag(features_caller, AST_FEATURE_PARKCALL) && i < len) {
4676  options[i++] = OPT_CALLER_PARKCALL;
4677  }
4678 
4679  if (ast_test_flag(features_callee, AST_FEATURE_REDIRECT) && i < len) {
4680  options[i++] = OPT_CALLEE_REDIRECT;
4681  }
4682  if (ast_test_flag(features_callee, AST_FEATURE_AUTOMON) && i < len) {
4683  options[i++] = OPT_CALLEE_AUTOMON;
4684  }
4685  if (ast_test_flag(features_callee, AST_FEATURE_DISCONNECT) && i < len) {
4686  options[i++] = OPT_CALLEE_DISCONNECT;
4687  }
4688  if (ast_test_flag(features_callee, AST_FEATURE_PARKCALL) && i < len) {
4689  options[i++] = OPT_CALLEE_PARKCALL;
4690  }
4691 
4692  return options;
4693 }
4694 
4695 /*!
4696  * \internal
4697  * \brief Run management on a parked call.
4698  *
4699  * \note The parkinglot parkings list is locked on entry.
4700  *
4701  * \retval TRUE if the parking completed.
4702  */
4703 static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
4704 {
4705  struct ast_channel *chan = pu->chan; /* shorthand */
4706  int tms; /* timeout for this item */
4707  int x; /* fd index in channel */
4708 
4709  tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
4710  if (tms > pu->parkingtime) {
4711  /*
4712  * Call has been parked too long.
4713  * Stop entertaining the caller.
4714  */
4715  switch (pu->hold_method) {
4716  case AST_CONTROL_HOLD:
4718  break;
4719  case AST_CONTROL_RINGING:
4720  ast_indicate(pu->chan, -1);
4721  break;
4722  default:
4723  break;
4724  }
4725  pu->hold_method = 0;
4726 
4727  /* Get chan, exten from derived kludge */
4728  if (pu->peername[0]) {
4729  char *peername;
4730  char *dash;
4731  char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
4732  int i;
4733 
4734  peername = ast_strdupa(pu->peername);
4735  dash = strrchr(peername, '-');
4736  if (dash) {
4737  *dash = '\0';
4738  }
4739 
4740  peername_flat = ast_strdupa(peername);
4741  for (i = 0; peername_flat[i]; i++) {
4742  if (peername_flat[i] == '/') {
4743  peername_flat[i] = '_';
4744  }
4745  }
4746 
4749  "Parking dial context '%s' does not exist and unable to create\n",
4751  } else {
4752  char returnexten[AST_MAX_EXTENSION];
4753  struct ast_datastore *features_datastore;
4754  struct ast_dial_features *dialfeatures;
4755 
4756  if (!strncmp(peername, "Parked/", 7)) {
4757  peername += 7;
4758  }
4759  /* If dahdi channel, add a ring cadence DAHDI/NNr3 (if parkingretdahdiring defined) */
4760  if (!ast_strlen_zero(parkingretdahdiring) && !strncasecmp(peername, "dahdi", 5))
4761  strncat(peername, parkingretdahdiring, 2);
4762 
4763  ast_channel_lock(chan);
4764  features_datastore = ast_channel_datastore_find(chan, &dial_features_info,
4765  NULL);
4766  if (features_datastore && (dialfeatures = features_datastore->data)) {
4767  char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
4768 
4769  snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername,
4770  callback_dialoptions(&dialfeatures->peer_features,
4771  &dialfeatures->my_features, buf, sizeof(buf)));
4772  } else { /* Existing default */
4773  ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n",
4774  chan->name);
4775  snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
4776  }
4777  ast_channel_unlock(chan);
4778 
4779 
4780  int parkdialprio = 1;
4781  char parkciddata[512];
4782  char parkalertinfodata[512];
4783  /* alter CALLERID(name) and add AlertInfo header if requested */
4785  snprintf(parkciddata, sizeof(parkciddata), "CALLERID(name)=%s", parkingretcidname);
4786  if (ast_add_extension(parking_con_dial, 1, peername_flat, parkdialprio++, NULL, NULL, "Set", strdup(parkciddata), ast_free_ptr, registrar))
4787  ast_log(LOG_ERROR, "Could not create parking return dial exten: %s@%s\n", peername_flat, parking_con_dial);
4788  }
4790  snprintf(parkalertinfodata, sizeof(parkalertinfodata), "Alert-Info: %s", parkingretalertinfo);
4791  if (ast_add_extension(parking_con_dial, 1, peername_flat, parkdialprio++, NULL, NULL, "SIPAddHeader", strdup(parkalertinfodata), ast_free_ptr, registrar))
4792  ast_log(LOG_ERROR, "Could not create parking return dial exten: %s@%s\n", peername_flat, parking_con_dial);
4793  }
4794  if (ast_add_extension(parking_con_dial, 1, peername_flat, parkdialprio, NULL, NULL,
4795  "Dial", ast_strdup(returnexten), ast_free_ptr, registrar)) {
4797  "Could not create parking return dial exten: %s@%s\n",
4798  peername_flat, parking_con_dial);
4799  }
4800  }
4801  if (pu->options_specified) {
4802  /*
4803  * Park() was called with overriding return arguments, respect
4804  * those arguments.
4805  */
4806  set_c_e_p(chan, pu->context, pu->exten, pu->priority);
4807  } else if (comebacktoorigin) {
4808  set_c_e_p(chan, parking_con_dial, peername_flat, 1);
4809  } else {
4810  char parkingslot[AST_MAX_EXTENSION];
4811 
4812  snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
4813  pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
4814  set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
4815  }
4816  } else {
4817  /*
4818  * They've been waiting too long, send them back to where they
4819  * came. Theoretically they should have their original
4820  * extensions and such, but we copy to be on the safe side.
4821  */
4822  set_c_e_p(chan, pu->context, pu->exten, pu->priority);
4823  }
4824  post_manager_event("ParkedCallTimeOut", pu);
4825  ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
4826 
4827  ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n",
4828  pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context,
4829  pu->chan->exten, pu->chan->priority);
4830 
4831  /* Start up the PBX, or hang them up */
4832  if (ast_pbx_start(chan)) {
4834  "Unable to restart the PBX for user on '%s', hanging them up...\n",
4835  pu->chan->name);
4836  ast_hangup(chan);
4837  }
4838 
4839  /* And take them out of the parking lot */
4840  return 1;
4841  }
4842 
4843  /* still within parking time, process descriptors */
4844  if (pfds) {
4845  for (x = 0; x < AST_MAX_FDS; x++) {
4846  struct ast_frame *f;
4847  int y;
4848 
4849  if (chan->fds[x] == -1) {
4850  continue; /* nothing on this descriptor */
4851  }
4852 
4853  for (y = 0; y < nfds; y++) {
4854  if (pfds[y].fd == chan->fds[x]) {
4855  /* Found poll record! */
4856  break;
4857  }
4858  }
4859  if (y == nfds) {
4860  /* Not found */
4861  continue;
4862  }
4863 
4864  if (!(pfds[y].revents & (POLLIN | POLLERR | POLLPRI))) {
4865  /* Next x */
4866  continue;
4867  }
4868 
4869  if (pfds[y].revents & POLLPRI) {
4871  } else {
4873  }
4874  chan->fdno = x;
4875 
4876  /* See if they need servicing */
4877  f = ast_read(pu->chan);
4878  /* Hangup? */
4879  if (!f || (f->frametype == AST_FRAME_CONTROL
4880  && f->subclass.integer == AST_CONTROL_HANGUP)) {
4881  if (f) {
4882  ast_frfree(f);
4883  }
4884  post_manager_event("ParkedCallGiveUp", pu);
4885  ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "ParkedCallGiveUp",
4886  NULL);
4887 
4888  /* There's a problem, hang them up */
4889  ast_verb(2, "%s got tired of being parked\n", chan->name);
4890  ast_hangup(chan);
4891 
4892  /* And take them out of the parking lot */
4893  return 1;
4894  } else {
4895  /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
4896  ast_frfree(f);
4897  if (pu->hold_method == AST_CONTROL_HOLD
4898  && pu->moh_trys < 3
4899  && !chan->generatordata) {
4900  ast_debug(1,
4901  "MOH on parked call stopped by outside source. Restarting on channel %s.\n",
4902  chan->name);
4904  S_OR(pu->parkinglot->cfg.mohclass, NULL),
4906  ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0));
4907  pu->moh_trys++;
4908  }
4909  break;
4910  }
4911  } /* End for */
4912  }
4913 
4914  /* mark fds for next round */
4915  for (x = 0; x < AST_MAX_FDS; x++) {
4916  if (chan->fds[x] > -1) {
4917  void *tmp = ast_realloc(*new_pfds,
4918  (*new_nfds + 1) * sizeof(struct pollfd));
4919 
4920  if (!tmp) {
4921  continue;
4922  }
4923  *new_pfds = tmp;
4924  (*new_pfds)[*new_nfds].fd = chan->fds[x];
4925  (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI;
4926  (*new_pfds)[*new_nfds].revents = 0;
4927  (*new_nfds)++;
4928  }
4929  }
4930  /* Keep track of our shortest wait */
4931  if (tms < *ms || *ms < 0) {
4932  *ms = tms;
4933  }
4934 
4935  /* Stay in the parking lot. */
4936  return 0;
4937 }
4938 
4939 /*! \brief Run management on parkinglots, called once per parkinglot */
4940 static void manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
4941 {
4942  struct parkeduser *pu;
4943  struct ast_context *con;
4944 
4945  /* Lock parkings list */
4946  AST_LIST_LOCK(&curlot->parkings);
4947  AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
4948  if (pu->notquiteyet) { /* Pretend this one isn't here yet */
4949  continue;
4950  }
4951  if (manage_parked_call(pu, pfds, nfds, new_pfds, new_nfds, ms)) {
4952  /* Parking is complete for this call so remove it from the parking lot. */
4954  if (con) {
4955  if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
4957  "Whoa, failed to remove the parking extension %s@%s!\n",
4959  }
4962  } else {
4964  "Whoa, parking lot '%s' context '%s' does not exist.\n",
4966  }
4969  ast_free(pu);
4970  }
4971  }
4973  AST_LIST_UNLOCK(&curlot->parkings);
4974 }
4975 
4976 /*!
4977  * \brief Take care of parked calls and unpark them if needed
4978  * \param ignore unused var.
4979  *
4980  * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
4981  * if so, remove channel from parking lot and return it to the extension that parked it.
4982  * Check if parked channel decided to hangup, wait until next FD via select().
4983  */
4984 static void *do_parking_thread(void *ignore)
4985 {
4986  struct pollfd *pfds = NULL, *new_pfds = NULL;
4987  int nfds = 0, new_nfds = 0;
4988 
4989  for (;;) {
4990  struct ao2_iterator iter;
4991  struct ast_parkinglot *curlot;
4992  int ms = -1; /* poll2 timeout, uninitialized */
4993 
4994  iter = ao2_iterator_init(parkinglots, 0);
4995  while ((curlot = ao2_iterator_next(&iter))) {
4996  manage_parkinglot(curlot, pfds, nfds, &new_pfds, &new_nfds, &ms);
4997  ao2_ref(curlot, -1);
4998  }
4999  ao2_iterator_destroy(&iter);
5000 
5001  /* Recycle */
5002  ast_free(pfds);
5003  pfds = new_pfds;
5004  nfds = new_nfds;
5005  new_pfds = NULL;
5006  new_nfds = 0;
5007 
5008  /* Wait for something to happen */
5009  ast_poll(pfds, nfds, ms);
5010  pthread_testcancel();
5011  }
5012  /* If this WERE reached, we'd need to free(pfds) */
5013  return NULL; /* Never reached */
5014 }
5015 
5016 /*! \brief Find parkinglot by name */
5017 static struct ast_parkinglot *find_parkinglot(const char *name)
5018 {
5019  struct ast_parkinglot *parkinglot;
5020 
5021  if (ast_strlen_zero(name)) {
5022  return NULL;
5023  }
5024 
5025  parkinglot = ao2_find(parkinglots, (void *) name, 0);
5026  if (parkinglot) {
5027  ast_debug(1, "Found Parking lot: %s\n", parkinglot->name);
5028  }
5029 
5030  return parkinglot;
5031 }
5032 
5033 /*! \brief Copy parkinglot and store it with new name */
5034 static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot)
5035 {
5036  struct ast_parkinglot *copylot;
5037 
5038  if ((copylot = find_parkinglot(name))) { /* Parkinglot with that name already exists */
5039  ao2_ref(copylot, -1);
5040  return NULL;
5041  }
5042 
5043  copylot = create_parkinglot(name);
5044  if (!copylot) {
5045  return NULL;
5046  }
5047 
5048  ast_debug(1, "Building parking lot %s\n", name);
5049 
5050  /* Copy the source parking lot configuration. */
5051  copylot->cfg = parkinglot->cfg;
5052 
5053  return copylot;
5054 }
5055 
5061 
5062 /*! \brief Park a call */
5063 static int park_call_exec(struct ast_channel *chan, const char *data)
5064 {
5065  struct ast_park_call_args args = { 0, };
5066  struct ast_flags flags = { 0 };
5068  int orig_priority;
5069  int res;
5070  const char *pl_name;
5071  char *parse;
5072  struct park_app_args app_args;
5073 
5074  /*
5075  * Cache the original channel name because we are going to
5076  * masquerade the channel. Prefer the BLINDTRANSFER channel
5077  * name over this channel name. BLINDTRANSFER could be set if
5078  * the parking access extension did not get detected and we are
5079  * executing the Park application from the dialplan.
5080  *
5081  * The orig_chan_name is used to return the call to the
5082  * originator on parking timeout.
5083  */
5085  pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"), chan->name));
5086 
5087  /* Answer if call is not up */
5088  if (chan->_state != AST_STATE_UP) {
5089  if (ast_answer(chan)) {
5090  return -1;
5091  }
5092 
5093  /* Sleep to allow VoIP streams to settle down */
5094  if (ast_safe_sleep(chan, 1000)) {
5095  return -1;
5096  }
5097  }
5098 
5099  /* Process the dialplan application options. */
5100  parse = ast_strdupa(data);
5101  AST_STANDARD_APP_ARGS(app_args, parse);
5102 
5103  if (!ast_strlen_zero(app_args.timeout)) {
5104  if (sscanf(app_args.timeout, "%30d", &args.timeout) != 1) {
5105  ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout);
5106  args.timeout = 0;
5107  }
5108  }
5109  if (!ast_strlen_zero(app_args.return_con)) {
5110  args.return_con = app_args.return_con;
5111  }
5112  if (!ast_strlen_zero(app_args.return_ext)) {
5113  args.return_ext = app_args.return_ext;
5114  }
5115  if (!ast_strlen_zero(app_args.return_pri)) {
5116  if (sscanf(app_args.return_pri, "%30d", &args.return_pri) != 1) {
5117  ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri);
5118  args.return_pri = 0;
5119  }
5120  }
5121 
5122  ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
5123  args.flags = flags.flags;
5124 
5125  /*
5126  * Setup the exten/priority to be s/1 since we don't know where
5127  * this call should return.
5128  */
5129  ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
5130  orig_priority = chan->priority;
5131  strcpy(chan->exten, "s");
5132  chan->priority = 1;
5133 
5134  /* Park the call */
5135  if (!ast_strlen_zero(app_args.pl_name)) {
5136  pl_name = app_args.pl_name;
5137  } else {
5138  pl_name = findparkinglotname(chan);
5139  }
5140  if (ast_strlen_zero(pl_name)) {
5141  /* Parking lot is not specified, so use the default parking lot. */
5143  } else {
5144  args.parkinglot = find_parkinglot(pl_name);
5145  if (!args.parkinglot && parkeddynamic) {
5146  args.parkinglot = create_dynamic_parkinglot(pl_name, chan);
5147  }
5148  }
5149  if (args.parkinglot) {
5150  res = masq_park_call(chan, chan, &args);
5152  } else {
5153  /* Parking failed because the parking lot does not exist. */
5154  if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
5155  ast_stream_and_wait(chan, "pbx-parkingfailed", "");
5156  }
5157  res = -1;
5158  }
5159  if (res) {
5160  /* Park failed, try to continue in the dialplan. */
5161  ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
5162  chan->priority = orig_priority;
5163  res = 0;
5164  } else {
5165  /* Park succeeded. */
5166  res = -1;
5167  }
5168 
5169  return res;
5170 }
5171 
5172 /*! \brief Pickup parked call */
5173 static int parked_call_exec(struct ast_channel *chan, const char *data)
5174 {
5175  int res;
5176  struct ast_channel *peer = NULL;
5177  struct parkeduser *pu;
5178  struct ast_context *con;
5179  char *parse;
5180  const char *pl_name;
5181  unsigned int park = 0;
5182  struct ast_bridge_config config;
5183  struct ast_parkinglot *parkinglot;
5184  AST_DECLARE_APP_ARGS(app_args,
5185  AST_APP_ARG(pl_space); /*!< Parking lot space to retrieve if present. */
5186  AST_APP_ARG(pl_name); /*!< Parking lot name to use if present. */
5187  AST_APP_ARG(dummy); /*!< Place to put any remaining args string. */
5188  );
5189 
5190  parse = ast_strdupa(data);
5191  AST_STANDARD_APP_ARGS(app_args, parse);
5192 
5193  if (!ast_strlen_zero(app_args.pl_space)) {
5194  if (sscanf(app_args.pl_space, "%30u", &park) != 1) {
5195  ast_log(LOG_WARNING, "Specified parking extension not a number: %s\n",
5196  app_args.pl_space);
5197  park = -1;
5198  }
5199  }
5200 
5201  if (!ast_strlen_zero(app_args.pl_name)) {
5202  pl_name = app_args.pl_name;
5203  } else {
5204  pl_name = findparkinglotname(chan);
5205  }
5206  if (ast_strlen_zero(pl_name)) {
5207  /* Parking lot is not specified, so use the default parking lot. */
5208  parkinglot = parkinglot_addref(default_parkinglot);
5209  } else {
5210  parkinglot = find_parkinglot(pl_name);
5211  if (!parkinglot) {
5212  /* It helps to answer the channel if not already up. :) */
5213  if (chan->_state != AST_STATE_UP) {
5214  ast_answer(chan);
5215  }
5216  if (ast_stream_and_wait(chan, "pbx-invalidpark", "")) {
5217  ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n",
5218  "pbx-invalidpark", chan->name);
5219  }
5221  "Channel %s tried to retrieve parked call from unknown parking lot '%s'\n",
5222  chan->name, pl_name);
5223  return -1;
5224  }
5225  }
5226 
5227  AST_LIST_LOCK(&parkinglot->parkings);
5228  AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot->parkings, pu, list) {
5229  if ((ast_strlen_zero(app_args.pl_space) || pu->parkingnum == park)
5230  && !pu->notquiteyet && !pu->chan->pbx) {
5231  /* The parking space has a call and can be picked up now. */
5233  break;
5234  }
5235  }
5237  if (pu) {
5238  /* Found a parked call to pickup. */
5239  peer = pu->chan;
5240  con = ast_context_find(parkinglot->cfg.parking_con);
5241  if (con) {
5242  if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
5243  ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
5244  } else {
5246  }
5247  } else {
5248  ast_log(LOG_WARNING, "Whoa, no parking context?\n");
5249  }
5250 
5251  ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "UnParkedCall", chan);
5252  ast_manager_event(pu->chan, EVENT_FLAG_CALL, "UnParkedCall",
5253  "Exten: %s\r\n"
5254  "Channel: %s\r\n"
5255  "Parkinglot: %s\r\n"
5256  "From: %s\r\n"
5257  "CallerIDNum: %s\r\n"
5258  "CallerIDName: %s\r\n"
5259  "ConnectedLineNum: %s\r\n"
5260  "ConnectedLineName: %s\r\n"
5261  "Uniqueid: %s\r\n",
5262  pu->parkingexten, pu->chan->name, pu->parkinglot->name, chan->name,
5263  S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
5264  S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
5265  S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
5266  S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
5267  pu->chan->uniqueid
5268  );
5269 
5270  /* Stop entertaining the caller. */
5271  switch (pu->hold_method) {
5272  case AST_CONTROL_HOLD:
5274  break;
5275  case AST_CONTROL_RINGING:
5276  ast_indicate(pu->chan, -1);
5277  break;
5278  default:
5279  break;
5280  }
5281  pu->hold_method = 0;
5282 
5284  ast_free(pu);
5285  }
5286  AST_LIST_UNLOCK(&parkinglot->parkings);
5287 
5288  if (peer) {
5289  /* Update connected line between retrieving call and parked call. */
5290  struct ast_party_connected_line connected;
5291 
5292  ast_party_connected_line_init(&connected);
5293 
5294  /* Send our caller-id to peer. */
5295  ast_channel_lock(chan);
5296  ast_connected_line_copy_from_caller(&connected, &chan->caller);
5297  ast_channel_unlock(chan);
5299  if (ast_channel_connected_line_macro(chan, peer, &connected, 0, 0)) {
5300  ast_channel_update_connected_line(peer, &connected, NULL);
5301  }
5302 
5303  /*
5304  * Get caller-id from peer.
5305  *
5306  * Update the retrieving call before it is answered if possible
5307  * for best results. Some phones do not support updating the
5308  * connected line information after connection.
5309  */
5310  ast_channel_lock(peer);
5311  ast_connected_line_copy_from_caller(&connected, &peer->caller);
5312  ast_channel_unlock(peer);
5314  if (ast_channel_connected_line_macro(peer, chan, &connected, 1, 0)) {
5315  ast_channel_update_connected_line(chan, &connected, NULL);
5316  }
5317 
5318  ast_party_connected_line_free(&connected);
5319  }
5320 
5321  /* JK02: it helps to answer the channel if not already up */
5322  if (chan->_state != AST_STATE_UP) {
5323  ast_answer(chan);
5324  }
5325 
5326  if (peer) {
5327  struct ast_datastore *features_datastore;
5328  struct ast_dial_features *dialfeatures;
5329 
5330  /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
5331  if (!ast_strlen_zero(courtesytone)) {
5332  static const char msg[] = "courtesy tone";
5333 
5334  switch (parkedplay) {
5335  case 0:/* Courtesy tone to pickup chan */
5336  res = play_message_to_chans(chan, peer, -1, msg, courtesytone);
5337  break;
5338  case 1:/* Courtesy tone to parked chan */
5339  res = play_message_to_chans(chan, peer, 1, msg, courtesytone);
5340  break;
5341  case 2:/* Courtesy tone to both chans */
5342  res = play_message_to_chans(chan, peer, 0, msg, courtesytone);
5343  break;
5344  default:
5345  res = 0;
5346  break;
5347  }
5348  if (res) {
5349  ast_hangup(peer);
5350  parkinglot_unref(parkinglot);
5351  return -1;
5352  }
5353  }
5354 
5355  res = ast_channel_make_compatible(chan, peer);
5356  if (res < 0) {
5357  ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
5358  ast_hangup(peer);
5359  parkinglot_unref(parkinglot);
5360  return -1;
5361  }
5362  /* This runs sorta backwards, since we give the incoming channel control, as if it
5363  were the person called. */
5364  ast_verb(3, "Channel %s connected to parked call %u\n", chan->name, park);
5365 
5366  pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
5367  ast_cdr_setdestchan(chan->cdr, peer->name);
5368  memset(&config, 0, sizeof(struct ast_bridge_config));
5369 
5370  /* Get datastore for peer and apply it's features to the callee side of the bridge config */
5371  ast_channel_lock(peer);
5372  features_datastore = ast_channel_datastore_find(peer, &dial_features_info, NULL);
5373  if (features_datastore && (dialfeatures = features_datastore->data)) {
5374  ast_copy_flags(&config.features_callee, &dialfeatures->my_features,
5375  AST_FLAGS_ALL);
5376  }
5377  ast_channel_unlock(peer);
5378 
5381  }
5384  }
5387  }
5390  }
5393  }
5396  }
5399  }
5402  }
5403 
5404  res = ast_bridge_call(chan, peer, &config);
5405 
5406  pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
5407  ast_cdr_setdestchan(chan->cdr, peer->name);
5408 
5409  /* Simulate the PBX hanging up */
5410  ast_hangup(peer);
5411  } else {
5412  if (ast_stream_and_wait(chan, "pbx-invalidpark", "")) {
5413  ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark",
5414  chan->name);
5415  }
5416  ast_verb(3, "Channel %s tried to retrieve nonexistent parked call %u\n",
5417  chan->name, park);
5418  res = -1;
5419  }
5420 
5421  parkinglot_unref(parkinglot);
5422  return res;
5423 }
5424 
5425 /*!
5426  * \brief Unreference parkinglot object.
5427  */
5428 static void parkinglot_unref(struct ast_parkinglot *parkinglot)
5429 {
5430  ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name,
5431  ao2_ref(parkinglot, 0) - 1);
5432  ao2_ref(parkinglot, -1);
5433 }
5434 
5435 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
5436 {
5437  int refcount;
5438 
5439  refcount = ao2_ref(parkinglot, +1);
5440  ast_debug(3, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
5441  return parkinglot;
5442 }
5443 
5444 /*! \brief Destroy a parking lot */
5445 static void parkinglot_destroy(void *obj)
5446 {
5447  struct ast_parkinglot *doomed = obj;
5448 
5449  /*
5450  * No need to destroy parked calls here because any parked call
5451  * holds a parking lot reference. Therefore the parkings list
5452  * must be empty.
5453  */
5454  ast_assert(AST_LIST_EMPTY(&doomed->parkings));
5455  AST_LIST_HEAD_DESTROY(&doomed->parkings);
5456 }
5457 
5458 /*! \brief Allocate parking lot structure */
5459 static struct ast_parkinglot *create_parkinglot(const char *name)
5460 {
5461  struct ast_parkinglot *newlot;
5462 
5463  if (ast_strlen_zero(name)) { /* No name specified */
5464  return NULL;
5465  }
5466 
5467  newlot = ao2_alloc(sizeof(*newlot), parkinglot_destroy);
5468  if (!newlot)
5469  return NULL;
5470 
5471  ast_copy_string(newlot->name, name, sizeof(newlot->name));
5472  newlot->cfg.is_invalid = 1;/* No config is set yet. */
5473  AST_LIST_HEAD_INIT(&newlot->parkings);
5474 
5475  return newlot;
5476 }
5477 
5478 /*!
5479  * \brief Add parking hints for all defined parking spaces.
5480  * \param context Dialplan context to add the hints.
5481  * \param start Starting space in parkinglot.
5482  * \param stop Ending space in parkinglot.
5483  */
5484 static void park_add_hints(const char *context, int start, int stop)
5485 {
5486  int numext;
5487  char device[AST_MAX_EXTENSION];
5488  char exten[10];
5489 
5490  for (numext = start; numext <= stop; numext++) {
5491  snprintf(exten, sizeof(exten), "%d", numext);
5492  snprintf(device, sizeof(device), "park:%s@%s", exten, context);
5493  ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
5494  }
5495 }
5496 
5497 /*! Default configuration for default parking lot. */
5499  .mohclass = "default",
5500  .parkext = DEFAULT_PARK_EXTENSION,
5501  .parking_con = "parkedcalls",
5502  .parking_start = 701,
5503  .parking_stop = 750,
5504  .parkingtime = DEFAULT_PARK_TIME,
5505 };
5506 
5507 /*! Default configuration for normal parking lots. */
5510  .parkingtime = DEFAULT_PARK_TIME,
5511 };
5512 
5513 /*!
5514  * \internal
5515  * \brief Set parking lot feature flag configuration value.
5516  *
5517  * \param pl_name Parking lot name for diagnostic messages.
5518  * \param param Parameter value to set.
5519  * \param var Current configuration variable item.
5520  *
5521  * \return Nothing
5522  */
5523 static void parkinglot_feature_flag_cfg(const char *pl_name, int *param, struct ast_variable *var)
5524 {
5525  ast_debug(1, "Setting parking lot %s %s to %s\n", pl_name, var->name, var->value);
5526  if (!strcasecmp(var->value, "both")) {
5527  *param = AST_FEATURE_FLAG_BYBOTH;
5528  } else if (!strcasecmp(var->value, "caller")) {
5529  *param = AST_FEATURE_FLAG_BYCALLER;
5530  } else if (!strcasecmp(var->value, "callee")) {
5531  *param = AST_FEATURE_FLAG_BYCALLEE;
5532  }
5533 }
5534 
5535 /*!
5536  * \internal
5537  * \brief Read parking lot configuration.
5538  *
5539  * \param pl_name Parking lot name for diagnostic messages.
5540  * \param cfg Parking lot config to update that is already initialized with defaults.
5541  * \param var Config variable list.
5542  *
5543  * \retval 0 on success.
5544  * \retval -1 on error.
5545  */
5546 static int parkinglot_config_read(const char *pl_name, struct parkinglot_cfg *cfg, struct ast_variable *var)
5547 {
5548  int error = 0;
5549 
5550  while (var) {
5551  if (!strcasecmp(var->name, "context")) {
5552  ast_copy_string(cfg->parking_con, var->value, sizeof(cfg->parking_con));
5553  } else if (!strcasecmp(var->name, "parkext")) {
5554  ast_copy_string(cfg->parkext, var->value, sizeof(cfg->parkext));
5555  } else if (!strcasecmp(var->name, "parkext_exclusive")) {
5556  cfg->parkext_exclusive = ast_true(var->value);
5557  } else if (!strcasecmp(var->name, "parkinghints")) {
5558  cfg->parkaddhints = ast_true(var->value);
5559  } else if (!strcasecmp(var->name, "parkedmusicclass")) {
5560  ast_copy_string(cfg->mohclass, var->value, sizeof(cfg->mohclass));
5561  } else if (!strcasecmp(var->name, "parkingtime")) {
5562  int parkingtime = 0;
5563 
5564  if ((sscanf(var->value, "%30d", &parkingtime) != 1) || parkingtime < 1) {
5565  ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
5566  error = -1;
5567  } else {
5568  cfg->parkingtime = parkingtime * 1000;
5569  }
5570  } else if (!strcasecmp(var->name, "parkpos")) {
5571  int start = 0;
5572  int end = 0;
5573 
5574  if (sscanf(var->value, "%30d-%30d", &start, &end) != 2) {
5576  "Format for parking positions is a-b, where a and b are numbers at line %d of %s\n",
5577  var->lineno, var->file);
5578  error = -1;
5579  } else if (end < start || start <= 0 || end <= 0) {
5580  ast_log(LOG_WARNING, "Parking range is invalid. Must be a <= b, at line %d of %s\n",
5581  var->lineno, var->file);
5582  error = -1;
5583  } else {
5584  cfg->parking_start = start;
5585  cfg->parking_stop = end;
5586  }
5587  } else if (!strcasecmp(var->name, "findslot")) {
5588  cfg->parkfindnext = (!strcasecmp(var->value, "next"));
5589  } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
5590  parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcalltransfers, var);
5591  } else if (!strcasecmp(var->name, "parkedcallreparking")) {
5592  parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallreparking, var);
5593  } else if (!strcasecmp(var->name, "parkedcallhangup")) {
5594  parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallhangup, var);
5595  } else if (!strcasecmp(var->name, "parkedcallrecording")) {
5596  parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallrecording, var);
5597  } else if (!strcasecmp(var->name, "parkingretcidname")) {
5599  } else if (!strcasecmp(var->name, "parkingretdahdiring")) {
5601  } else if (!strcasecmp(var->name, "parkingretalertinfo")) {
5603  }
5604  var = var->next;
5605  }
5606 
5607  /* Check for configuration errors */
5608  if (ast_strlen_zero(cfg->parking_con)) {
5609  ast_log(LOG_WARNING, "Parking lot %s needs context\n", pl_name);
5610  error = -1;
5611  }
5612  if (ast_strlen_zero(cfg->parkext)) {
5613  ast_log(LOG_WARNING, "Parking lot %s needs parkext\n", pl_name);
5614  error = -1;
5615  }
5616  if (!cfg->parking_start) {
5617  ast_log(LOG_WARNING, "Parking lot %s needs parkpos\n", pl_name);
5618  error = -1;
5619  }
5620  if (error) {
5621  cfg->is_invalid = 1;
5622  }
5623 
5624  return error;
5625 }
5626 
5627 /*!
5628  * \internal
5629  * \brief Activate the given parkinglot.
5630  *
5631  * \param parkinglot Parking lot to activate.
5632  *
5633  * \details
5634  * Insert into the dialplan the context, parking lot access
5635  * extension, and optional dialplan hints.
5636  *
5637  * \retval 0 on success.
5638  * \retval -1 on error.
5639  */
5640 static int parkinglot_activate(struct ast_parkinglot *parkinglot)
5641 {
5642  int disabled = 0;
5643  char app_data[5 + AST_MAX_CONTEXT];
5644 
5645  /* Create Park option list. Must match with struct park_app_args options. */
5646  if (parkinglot->cfg.parkext_exclusive) {
5647  /* Specify the parking lot this parking extension parks calls. */
5648  snprintf(app_data, sizeof(app_data), ",,,,,%s", parkinglot->name);
5649  } else {
5650  /* The dialplan must specify which parking lot to use. */
5651  app_data[0] = '\0';
5652  }
5653 
5654  /* Create context */
5655  if (!ast_context_find_or_create(NULL, NULL, parkinglot->cfg.parking_con, registrar)) {
5656  ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n",
5657  parkinglot->cfg.parking_con);
5658  disabled = 1;
5659 
5660  /* Add a parking extension into the context */
5661  } else if (ast_add_extension(parkinglot->cfg.parking_con, 1, parkinglot->cfg.parkext,
5662  1, NULL, NULL, parkcall, ast_strdup(app_data), ast_free_ptr, registrar)) {
5663  ast_log(LOG_ERROR, "Could not create parking lot %s access exten %s@%s\n",
5664  parkinglot->name, parkinglot->cfg.parkext, parkinglot->cfg.parking_con);
5665  disabled = 1;
5666  } else {
5667  /* Add parking hints */
5668  if (parkinglot->cfg.parkaddhints) {
5669  park_add_hints(parkinglot->cfg.parking_con, parkinglot->cfg.parking_start,
5670  parkinglot->cfg.parking_stop);
5671  }
5672 
5673  /*
5674  * XXX Not sure why we should need to notify the metermaids for
5675  * this exten. It was originally done for the default parking
5676  * lot entry exten only but should be done for all entry extens
5677  * if we do it for one.
5678  */
5679  /* Notify metermaids about parking lot entry exten state. */
5680  notify_metermaids(parkinglot->cfg.parkext, parkinglot->cfg.parking_con,
5682  }
5683 
5684  parkinglot->disabled = disabled;
5685  return disabled ? -1 : 0;
5686 }
5687 
5688 /*! \brief Build parkinglot from configuration and chain it in if it doesn't already exist */
5689 static struct ast_parkinglot *build_parkinglot(const char *pl_name, struct ast_variable *var)
5690 {
5691  struct ast_parkinglot *parkinglot;
5692  const struct parkinglot_cfg *cfg_defaults;
5693  struct parkinglot_cfg new_cfg;
5694  int cfg_error;
5695  int oldparkinglot = 0;
5696 
5697  parkinglot = find_parkinglot(pl_name);
5698  if (parkinglot) {
5699  oldparkinglot = 1;
5700  } else {
5701  parkinglot = create_parkinglot(pl_name);
5702  if (!parkinglot) {
5703  return NULL;
5704  }
5705  }
5706  if (!strcmp(parkinglot->name, DEFAULT_PARKINGLOT)) {
5707  cfg_defaults = &parkinglot_cfg_default_default;
5708  } else {
5709  cfg_defaults = &parkinglot_cfg_default;
5710  }
5711  new_cfg = *cfg_defaults;
5712 
5713  ast_debug(1, "Building parking lot %s\n", parkinglot->name);
5714 
5715  ao2_lock(parkinglot);
5716 
5717  /* Do some config stuff */
5718  cfg_error = parkinglot_config_read(parkinglot->name, &new_cfg, var);
5719  if (oldparkinglot) {
5720  if (cfg_error) {
5721  /* Bad configuration read. Keep using the original config. */
5722  ast_log(LOG_WARNING, "Changes to parking lot %s are discarded.\n",
5723  parkinglot->name);
5724  cfg_error = 0;
5725  } else if (!AST_LIST_EMPTY(&parkinglot->parkings)
5726  && memcmp(&new_cfg, &parkinglot->cfg, sizeof(parkinglot->cfg))) {
5727  /* Try reloading later when parking lot is empty. */
5729  "Parking lot %s has parked calls. Parking lot changes discarded.\n",
5730  parkinglot->name);
5731  force_reload_load = 1;
5732  } else {
5733  /* Accept the new config */
5734  parkinglot->cfg = new_cfg;
5735  }
5736  } else {
5737  /* Load the initial parking lot config. */
5738  parkinglot->cfg = new_cfg;
5739  }
5740  parkinglot->the_mark = 0;
5741 
5742  ao2_unlock(parkinglot);
5743 
5744  if (cfg_error) {
5745  /* Only new parking lots could have config errors here. */
5746  ast_log(LOG_WARNING, "New parking lot %s is discarded.\n", parkinglot->name);
5747  parkinglot_unref(parkinglot);
5748  return NULL;
5749  }
5750 
5751  /* Move it into the list, if it wasn't already there */
5752  if (!oldparkinglot) {
5753  ao2_link(parkinglots, parkinglot);
5754  }
5755  parkinglot_unref(parkinglot);
5756 
5757  return parkinglot;
5758 }
5759 
5760 /*!
5761  * \internal
5762  * \brief Process an applicationmap section config line.
5763  *
5764  * \param var Config variable line.
5765  *
5766  * \return Nothing
5767  */
5769 {
5770  char *tmp_val = ast_strdupa(var->value);
5771  char *activateon, *new_syn;
5772  struct ast_call_feature *feature;
5774  AST_APP_ARG(exten);
5775  AST_APP_ARG(activatedby);
5776  AST_APP_ARG(app);
5779  );
5780 
5781  AST_STANDARD_APP_ARGS(args, tmp_val);
5782 
5783  activateon = strsep(&args.activatedby, "/");
5784 
5785  if (ast_strlen_zero(args.app)
5786  || ast_strlen_zero(args.exten)
5787  || ast_strlen_zero(activateon)
5788  || ast_strlen_zero(var->name)) {
5790  "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
5791  args.app, args.exten, activateon, var->name);
5792  return;
5793  }
5794 
5795  if ((new_syn = strchr(args.app, '('))) {
5796  /* New syntax */
5797  args.moh_class = args.app_args;
5798  args.app_args = new_syn;
5799  *args.app_args++ = '\0';
5800  if (args.app_args[strlen(args.app_args) - 1] == ')') {
5801  args.app_args[strlen(args.app_args) - 1] = '\0';
5802  }
5803  }
5804 
5806  if (find_dynamic_feature(var->name)) {
5808  ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n",
5809  var->name);
5810  return;
5811  }
5813 
5814  if (!(feature = ast_calloc(1, sizeof(*feature)))) {
5815  return;
5816  }
5817 
5818  ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
5819  ast_copy_string(feature->app, args.app, FEATURE_APP_LEN);
5820  ast_copy_string(feature->exten, args.exten, FEATURE_EXTEN_LEN);
5821 
5822  if (args.app_args) {
5823  ast_copy_string(feature->app_args, args.app_args, FEATURE_APP_ARGS_LEN);
5824  }
5825 
5826  if (args.moh_class) {
5827  ast_copy_string(feature->moh_class, args.moh_class, FEATURE_MOH_LEN);
5828  }
5829 
5830  ast_copy_string(feature->exten, args.exten, sizeof(feature->exten));
5831  feature->operation = feature_exec_app;
5833 
5834  /* Allow caller and callee to be specified for backwards compatability */
5835  if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller")) {
5837  } else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee")) {
5839  } else {
5840  ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
5841  " must be 'self', or 'peer'\n", var->name);
5842  ast_free(feature);
5843  return;
5844  }
5845 
5846  if (ast_strlen_zero(args.activatedby)) {
5848  } else if (!strcasecmp(args.activatedby, "caller")) {
5850  } else if (!strcasecmp(args.activatedby, "callee")) {
5852  } else if (!strcasecmp(args.activatedby, "both")) {
5854  } else {
5855  ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
5856  " must be 'caller', or 'callee', or 'both'\n", var->name);
5857  ast_free(feature);
5858  return;
5859  }
5860 
5861  ast_register_feature(feature);
5862 
5863  ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n",
5864  var->name, args.app, args.app_args, args.exten);
5865 }
5866 
5867 static int process_config(struct ast_config *cfg)
5868 {
5869  int i;
5870  struct ast_variable *var = NULL;
5871  struct feature_group *fg = NULL;
5872  char *ctg;
5873  static const char * const categories[] = {
5874  /* Categories in features.conf that are not
5875  * to be parsed as group categories
5876  */
5877  "general",
5878  "featuremap",
5879  "applicationmap"
5880  };
5881 
5882  /* Set general features global defaults. */
5884 
5885  /* Set global call pickup defaults. */
5886  strcpy(pickup_ext, "*8");
5887  pickupsound[0] = '\0';
5888  pickupfailsound[0] = '\0';
5889 
5890  /* Set global call transfer defaults. */
5891  strcpy(xfersound, "beep");
5892  strcpy(xferfailsound, "beeperr");
5898 
5899  /* Set global call parking defaults. */
5900  comebacktoorigin = 1;
5901  courtesytone[0] = '\0';
5902  parkedplay = 0;
5903  adsipark = 0;
5904  parkeddynamic = 0;
5905 
5906  var = ast_variable_browse(cfg, "general");
5908  for (; var; var = var->next) {
5909  if (!strcasecmp(var->name, "parkeddynamic")) {
5910  parkeddynamic = ast_true(var->value);
5911  } else if (!strcasecmp(var->name, "adsipark")) {
5912  adsipark = ast_true(var->value);
5913  } else if (!strcasecmp(var->name, "transferdigittimeout")) {
5914  if ((sscanf(var->value, "%30d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
5915  ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
5917  } else {
5919  }
5920  } else if (!strcasecmp(var->name, "featuredigittimeout")) {
5921  if ((sscanf(var->value, "%30d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
5922  ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
5924  }
5925  } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
5926  if ((sscanf(var->value, "%30d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
5927  ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
5929  } else {
5931  }
5932  } else if (!strcasecmp(var->name, "atxferloopdelay")) {
5933  if ((sscanf(var->value, "%30u", &atxferloopdelay) != 1)) {
5934  ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
5936  } else {
5937  atxferloopdelay *= 1000;
5938  }
5939  } else if (!strcasecmp(var->name, "atxferdropcall")) {
5940  atxferdropcall = ast_true(var->value);
5941  } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
5942  if ((sscanf(var->value, "%30u", &atxfercallbackretries) != 1)) {
5943  ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
5945  }
5946  } else if (!strcasecmp(var->name, "courtesytone")) {
5948  } else if (!strcasecmp(var->name, "parkedplay")) {
5949  if (!strcasecmp(var->value, "both")) {
5950  parkedplay = 2;
5951  } else if (!strcasecmp(var->value, "parked")) {
5952  parkedplay = 1;
5953  } else {
5954  parkedplay = 0;
5955  }
5956  } else if (!strcasecmp(var->name, "xfersound")) {
5957  ast_copy_string(xfersound, var->value, sizeof(xfersound));
5958  } else if (!strcasecmp(var->name, "xferfailsound")) {
5960  } else if (!strcasecmp(var->name, "pickupexten")) {
5961  ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
5962  } else if (!strcasecmp(var->name, "pickupsound")) {
5963  ast_copy_string(pickupsound, var->value, sizeof(pickupsound));
5964  } else if (!strcasecmp(var->name, "pickupfailsound")) {
5966  } else if (!strcasecmp(var->name, "comebacktoorigin")) {
5968  }
5969  }
5970 
5971  unmap_features();
5972  for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
5973  if (remap_feature(var->name, var->value)) {
5974  ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
5975  }
5976  }
5977 
5978  /* Map a key combination to an application */
5980  for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
5982  }
5983 
5986 
5987  ctg = NULL;
5988  while ((ctg = ast_category_browse(cfg, ctg))) {
5989  /* Is this a parkinglot definition ? */
5990  if (!strncasecmp(ctg, "parkinglot_", strlen("parkinglot_"))) {
5991  ast_debug(2, "Found configuration section %s, assume parking context\n", ctg);
5992  if (!build_parkinglot(ctg, ast_variable_browse(cfg, ctg))) {
5993  ast_log(LOG_ERROR, "Could not build parking lot %s. Configuration error.\n", ctg);
5994  } else {
5995  ast_debug(1, "Configured parking context %s\n", ctg);
5996  }
5997  continue;
5998  }
5999 
6000  /* No, check if it's a group */
6001  for (i = 0; i < ARRAY_LEN(categories); i++) {
6002  if (!strcasecmp(categories[i], ctg)) {
6003  break;
6004  }
6005  }
6006  if (i < ARRAY_LEN(categories)) {
6007  continue;
6008  }
6009 
6010  if (!(fg = register_group(ctg))) {
6011  continue;
6012  }
6013 
6014  for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
6015  struct ast_call_feature *feature;
6016 
6018  if (!(feature = find_dynamic_feature(var->name)) &&
6019  !(feature = ast_find_call_feature(var->name))) {
6021  ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
6022  continue;
6023  }
6025 
6026  register_group_feature(fg, var->value, feature);
6027  }
6028  }
6029 
6031 
6032  return 0;
6033 }
6034 
6035 /*!
6036  * \internal
6037  * \brief Destroy the given dialplan usage context.
6038  *
6039  * \param doomed Parking lot usage context to destroy.
6040  *
6041  * \return Nothing
6042  */
6043 static void destroy_dialplan_usage_context(struct parking_dp_context *doomed)
6044 {
6045  struct parking_dp_ramp *ramp;
6046  struct parking_dp_spaces *spaces;
6047 
6048  while ((ramp = AST_LIST_REMOVE_HEAD(&doomed->access_extens, node))) {
6049  ast_free(ramp);
6050  }
6051  while ((spaces = AST_LIST_REMOVE_HEAD(&doomed->spaces, node))) {
6052  ast_free(spaces);
6053  }
6054  while ((spaces = AST_LIST_REMOVE_HEAD(&doomed->hints, node))) {
6055  ast_free(spaces);
6056  }
6057  ast_free(doomed);
6058 }
6059 
6060 /*!
6061  * \internal
6062  * \brief Destroy the given dialplan usage map.
6063  *
6064  * \param doomed Parking lot usage map to destroy.
6065  *
6066  * \return Nothing
6067  */
6068 static void destroy_dialplan_usage_map(struct parking_dp_map *doomed)
6069 {
6070  struct parking_dp_context *item;
6071 
6072  while ((item = AST_LIST_REMOVE_HEAD(doomed, node))) {
6074  }
6075 }
6076 
6077 /*!
6078  * \internal
6079  * \brief Create a new parking lot ramp dialplan usage node.
6080  *
6081  * \param exten Parking lot access ramp extension.
6082  * \param exclusive TRUE if the parking lot access ramp extension is exclusive.
6083  *
6084  * \retval New usage ramp node on success.
6085  * \retval NULL on error.
6086  */
6087 static struct parking_dp_ramp *build_dialplan_useage_ramp(const char *exten, int exclusive)
6088 {
6089  struct parking_dp_ramp *ramp_node;
6090 
6091  ramp_node = ast_calloc(1, sizeof(*ramp_node) + strlen(exten));
6092  if (!ramp_node) {
6093  return NULL;
6094  }
6095  ramp_node->exclusive = exclusive;
6096  strcpy(ramp_node->exten, exten);
6097  return ramp_node;
6098 }
6099 
6100 /*!
6101  * \internal
6102  * \brief Add parking lot access ramp to the context ramp usage map.
6103  *
6104  * \param ramp_map Current parking lot context ramp usage map.
6105  * \param exten Parking lot access ramp extension to add.
6106  * \param exclusive TRUE if the parking lot access ramp extension is exclusive.
6107  * \param lot Parking lot supplying reference data.
6108  * \param complain TRUE if to complain of parking lot ramp conflicts.
6109  *
6110  * \retval 0 on success. The ramp_map is updated.
6111  * \retval -1 on failure.
6112  */
6113 static int usage_context_add_ramp(struct parking_dp_ramp_map *ramp_map, const char *exten, int exclusive, struct ast_parkinglot *lot, int complain)
6114 {
6115  struct parking_dp_ramp *cur_ramp;
6116  struct parking_dp_ramp *new_ramp;
6117  int cmp;
6118 
6119  /* Make sure that exclusive is only 0 or 1 */
6120  if (exclusive) {
6121  exclusive = 1;
6122  }
6123 
6124  AST_LIST_TRAVERSE_SAFE_BEGIN(ramp_map, cur_ramp, node) {
6125  cmp = strcmp(exten, cur_ramp->exten);
6126  if (cmp > 0) {
6127  /* The parking lot ramp goes after this node. */
6128  continue;
6129  }
6130  if (cmp == 0) {
6131  /* The ramp is already in the map. */
6132  if (complain && (cur_ramp->exclusive || exclusive)) {
6134  "Parking lot '%s' parkext %s@%s used by another parking lot.\n",
6135  lot->name, exten, lot->cfg.parking_con);
6136  }
6137  return 0;
6138  }
6139  /* The new parking lot ramp goes before this node. */
6140  new_ramp = build_dialplan_useage_ramp(exten, exclusive);
6141  if (!new_ramp) {
6142  return -1;
6143  }
6144  AST_LIST_INSERT_BEFORE_CURRENT(new_ramp, node);
6145  return 0;
6146  }
6148 
6149  /* New parking lot access ramp goes on the end. */
6150  new_ramp = build_dialplan_useage_ramp(exten, exclusive);
6151  if (!new_ramp) {
6152  return -1;
6153  }
6154  AST_LIST_INSERT_TAIL(ramp_map, new_ramp, node);
6155  return 0;
6156 }
6157 
6158 /*!
6159  * \internal
6160  * \brief Create a new parking lot spaces dialplan usage node.
6161  *
6162  * \param start First parking lot space to add.
6163  * \param stop Last parking lot space to add.
6164  *
6165  * \retval New usage ramp node on success.
6166  * \retval NULL on error.
6167  */
6168 static struct parking_dp_spaces *build_dialplan_useage_spaces(int start, int stop)
6169 {
6170  struct parking_dp_spaces *spaces_node;
6171 
6172  spaces_node = ast_calloc(1, sizeof(*spaces_node));
6173  if (!spaces_node) {
6174  return NULL;
6175  }
6176  spaces_node->start = start;
6177  spaces_node->stop = stop;
6178  return spaces_node;
6179 }
6180 
6181 /*!
6182  * \internal
6183  * \brief Add parking lot spaces to the context space usage map.
6184  *
6185  * \param space_map Current parking lot context space usage map.
6186  * \param start First parking lot space to add.
6187  * \param stop Last parking lot space to add.
6188  * \param lot Parking lot supplying reference data.
6189  * \param complain TRUE if to complain of parking lot spaces conflicts.
6190  *
6191  * \retval 0 on success. The space_map is updated.
6192  * \retval -1 on failure.
6193  */
6194 static int usage_context_add_spaces(struct parking_dp_space_map *space_map, int start, int stop, struct ast_parkinglot *lot, int complain)
6195 {
6196  struct parking_dp_spaces *cur_node;
6197  struct parking_dp_spaces *expand_node;
6198  struct parking_dp_spaces *new_node;
6199 
6200  expand_node = NULL;
6201  AST_LIST_TRAVERSE_SAFE_BEGIN(space_map, cur_node, node) {
6202  /* NOTE: stop + 1 to combine immediately adjacent nodes into one. */
6203  if (expand_node) {
6204  /* The previous node is expanding to possibly eat following nodes. */
6205  if (expand_node->stop + 1 < cur_node->start) {
6206  /* Current node is completely after expanding node. */
6207  return 0;
6208  }
6209 
6210  if (complain
6211  && ((cur_node->start <= start && start <= cur_node->stop)
6212  || (cur_node->start <= stop && stop <= cur_node->stop)
6213  || (start < cur_node->start && cur_node->stop < stop))) {
6214  /* Only complain once per range add. */
6215  complain = 0;
6217  "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
6218  lot->name, start, stop, lot->cfg.parking_con);
6219  }
6220 
6221  /* Current node is eaten by the expanding node. */
6222  if (expand_node->stop < cur_node->stop) {
6223  expand_node->stop = cur_node->stop;
6224  }
6226  ast_free(cur_node);
6227  continue;
6228  }
6229 
6230  if (cur_node->stop + 1 < start) {
6231  /* New range is completely after current node. */
6232  continue;
6233  }
6234  if (stop + 1 < cur_node->start) {
6235  /* New range is completely before current node. */
6236  new_node = build_dialplan_useage_spaces(start, stop);
6237  if (!new_node) {
6238  return -1;
6239  }
6240  AST_LIST_INSERT_BEFORE_CURRENT(new_node, node);
6241  return 0;
6242  }
6243 
6244  if (complain
6245  && ((cur_node->start <= start && start <= cur_node->stop)
6246  || (cur_node->start <= stop && stop <= cur_node->stop)
6247  || (start < cur_node->start && cur_node->stop < stop))) {
6248  /* Only complain once per range add. */
6249  complain = 0;
6251  "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
6252  lot->name, start, stop, lot->cfg.parking_con);
6253  }
6254 
6255  /* Current node range overlaps or is immediately adjacent to new range. */
6256  if (start < cur_node->start) {
6257  /* Expand the current node in the front. */
6258  cur_node->start = start;
6259  }
6260  if (stop <= cur_node->stop) {
6261  /* Current node is not expanding in the rear. */
6262  return 0;
6263  }
6264  cur_node->stop = stop;
6265  expand_node = cur_node;
6266  }
6268 
6269  if (expand_node) {
6270  /*
6271  * The previous node expanded and either ate all following nodes
6272  * or it was the last node.
6273  */
6274  return 0;
6275  }
6276 
6277  /* New range goes on the end. */
6278  new_node = build_dialplan_useage_spaces(start, stop);
6279  if (!new_node) {
6280  return -1;
6281  }
6282  AST_LIST_INSERT_TAIL(space_map, new_node, node);
6283  return 0;
6284 }
6285 
6286 /*!
6287  * \internal
6288  * \brief Add parking lot spaces to the context dialplan usage node.
6289  *
6290  * \param ctx_node Usage node to add parking lot spaces.
6291  * \param lot Parking lot to add data to ctx_node.
6292  * \param complain TRUE if to complain of parking lot ramp and spaces conflicts.
6293  *
6294  * \retval 0 on success.
6295  * \retval -1 on error.
6296  */
6297 static int dialplan_usage_add_parkinglot_data(struct parking_dp_context *ctx_node, struct ast_parkinglot *lot, int complain)
6298 {
6299  if (usage_context_add_ramp(&ctx_node->access_extens, lot->cfg.parkext,
6300  lot->cfg.parkext_exclusive, lot, complain)) {
6301  return -1;
6302  }
6303  if (usage_context_add_spaces(&ctx_node->spaces, lot->cfg.parking_start,
6304  lot->cfg.parking_stop, lot, complain)) {
6305  return -1;
6306  }
6307  if (lot->cfg.parkaddhints
6308  && usage_context_add_spaces(&ctx_node->hints, lot->cfg.parking_start,
6309  lot->cfg.parking_stop, lot, 0)) {
6310  return -1;
6311  }
6312  return 0;
6313 }
6314 
6315 /*!
6316  * \internal
6317  * \brief Create a new parking lot context dialplan usage node.
6318  *
6319  * \param lot Parking lot to create a new dialplan usage from.
6320  *
6321  * \retval New usage context node on success.
6322  * \retval NULL on error.
6323  */
6324 static struct parking_dp_context *build_dialplan_useage_context(struct ast_parkinglot *lot)
6325 {
6326  struct parking_dp_context *ctx_node;
6327 
6328  ctx_node = ast_calloc(1, sizeof(*ctx_node) + strlen(lot->cfg.parking_con));
6329  if (!ctx_node) {
6330  return NULL;
6331  }
6332  if (dialplan_usage_add_parkinglot_data(ctx_node, lot, 0)) {
6334  return NULL;
6335  }
6336  strcpy(ctx_node->context, lot->cfg.parking_con);
6337  return ctx_node;
6338 }
6339 
6340 /*!
6341  * \internal
6342  * \brief Add the given parking lot dialplan usage to the dialplan usage map.
6343  *
6344  * \param usage_map Parking lot usage map to add the given parking lot.
6345  * \param lot Parking lot to add dialplan usage.
6346  * \param complain TRUE if to complain of parking lot ramp and spaces conflicts.
6347  *
6348  * \retval 0 on success.
6349  * \retval -1 on error.
6350  */
6351 static int dialplan_usage_add_parkinglot(struct parking_dp_map *usage_map, struct ast_parkinglot *lot, int complain)
6352 {
6353  struct parking_dp_context *cur_ctx;
6354  struct parking_dp_context *new_ctx;
6355  int cmp;
6356 
6357  AST_LIST_TRAVERSE_SAFE_BEGIN(usage_map, cur_ctx, node) {
6358  cmp = strcmp(lot->cfg.parking_con, cur_ctx->context);
6359  if (cmp > 0) {
6360  /* The parking lot context goes after this node. */
6361  continue;
6362  }
6363  if (cmp == 0) {
6364  /* This is the node we will add parking lot spaces to the map. */
6365  return dialplan_usage_add_parkinglot_data(cur_ctx, lot, complain);
6366  }
6367  /* The new parking lot context goes before this node. */
6368  new_ctx = build_dialplan_useage_context(lot);
6369  if (!new_ctx) {
6370  return -1;
6371  }
6372  AST_LIST_INSERT_BEFORE_CURRENT(new_ctx, node);
6373  return 0;
6374  }
6376 
6377  /* New parking lot context goes on the end. */
6378  new_ctx = build_dialplan_useage_context(lot);
6379  if (!new_ctx) {
6380  return -1;
6381  }
6382  AST_LIST_INSERT_TAIL(usage_map, new_ctx, node);
6383  return 0;
6384 }
6385 
6386 /*!
6387  * \internal
6388  * \brief Build the dialplan usage map of the current parking lot container.
6389  *
6390  * \param usage_map Parking lot usage map. Must already be initialized.
6391  * \param complain TRUE if to complain of parking lot ramp and spaces conflicts.
6392  *
6393  * \retval 0 on success. The usage_map is filled in.
6394  * \retval -1 on failure. Built usage_map is incomplete.
6395  */
6396 static int build_dialplan_useage_map(struct parking_dp_map *usage_map, int complain)
6397 {
6398  int status = 0;
6399  struct ao2_iterator iter;
6400  struct ast_parkinglot *curlot;
6401 
6402  /* For all parking lots */
6403  iter = ao2_iterator_init(parkinglots, 0);
6404  for (; (curlot = ao2_iterator_next(&iter)); ao2_ref(curlot, -1)) {
6405  /* Add the parking lot to the map. */
6406  if (dialplan_usage_add_parkinglot(usage_map, curlot, complain)) {
6407  ao2_ref(curlot, -1);
6408  status = -1;
6409  break;
6410  }
6411  }
6412  ao2_iterator_destroy(&iter);
6413 
6414  return status;
6415 }
6416 
6417 /*!
6418  * \internal
6419  * \brief Remove the given extension if it exists.
6420  *
6421  * \param context Dialplan database context name.
6422  * \param exten Extension to remove.
6423  * \param priority Extension priority to remove.
6424  *
6425  * \return Nothing
6426  */
6427 static void remove_exten_if_exist(const char *context, const char *exten, int priority)
6428 {
6429  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
6430 
6431  if (pbx_find_extension(NULL, NULL, &q, context, exten, priority, NULL, NULL,
6432  E_MATCH)) {
6433  ast_debug(1, "Removing unneeded parking lot exten: %s@%s priority:%d\n",
6434  context, exten, priority);
6435  ast_context_remove_extension(context, exten, priority, registrar);
6436  }
6437 }
6438 
6439 /*!
6440  * \internal
6441  * \brief Remove unused parking lot access ramp items.
6442  *
6443  * \param context Dialplan database context name.
6444  * \param old_ramps Before configuration reload access ramp usage map.
6445  * \param new_ramps After configuration reload access ramp usage map.
6446  *
6447  * \details
6448  * Remove access ramp items that were in the old context but not in the
6449  * new context.
6450  *
6451  * \return Nothing
6452  */
6453 static void remove_dead_ramp_usage(const char *context, struct parking_dp_ramp_map *old_ramps, struct parking_dp_ramp_map *new_ramps)
6454 {
6455  struct parking_dp_ramp *old_ramp;
6456  struct parking_dp_ramp *new_ramp;
6457  int cmp;
6458 
6459  old_ramp = AST_LIST_FIRST(old_ramps);
6460  new_ramp = AST_LIST_FIRST(new_ramps);
6461 
6462  while (new_ramp) {
6463  if (!old_ramp) {
6464  /* No old ramps left, so no dead ramps can remain. */
6465  return;
6466  }
6467  cmp = strcmp(old_ramp->exten, new_ramp->exten);
6468  if (cmp < 0) {
6469  /* New map does not have old ramp. */
6470  remove_exten_if_exist(context, old_ramp->exten, 1);
6471  old_ramp = AST_LIST_NEXT(old_ramp, node);
6472  continue;
6473  }
6474  if (cmp == 0) {
6475  /* Old and new map have this ramp. */
6476  old_ramp = AST_LIST_NEXT(old_ramp, node);
6477  } else {
6478  /* Old map does not have new ramp. */
6479  }
6480  new_ramp = AST_LIST_NEXT(new_ramp, node);
6481  }
6482 
6483  /* Any old ramps left must be dead. */
6484  for (; old_ramp; old_ramp = AST_LIST_NEXT(old_ramp, node)) {
6485  remove_exten_if_exist(context, old_ramp->exten, 1);
6486  }
6487 }
6488 
6489 /*!
6490  * \internal
6491  * \brief Destroy the given parking space.
6492  *
6493  * \param context Dialplan database context name.
6494  * \param space Parking space.
6495  *
6496  * \return Nothing
6497  */
6498 static void destroy_space(const char *context, int space)
6499 {
6500  char exten[AST_MAX_EXTENSION];
6501 
6502  /* Destroy priorities of the parking space that we registered. */
6503  snprintf(exten, sizeof(exten), "%d", space);
6504  remove_exten_if_exist(context, exten, PRIORITY_HINT);
6505  remove_exten_if_exist(context, exten, 1);
6506 }
6507 
6508 /*!
6509  * \internal
6510  * \brief Remove unused parking lot space items.
6511  *
6512  * \param context Dialplan database context name.
6513  * \param old_spaces Before configuration reload parking space usage map.
6514  * \param new_spaces After configuration reload parking space usage map.
6515  * \param destroy_space Function to destroy parking space item.
6516  *
6517  * \details
6518  * Remove parking space items that were in the old context but
6519  * not in the new context.
6520  *
6521  * \return Nothing
6522  */
6523 static void remove_dead_spaces_usage(const char *context,
6524  struct parking_dp_space_map *old_spaces, struct parking_dp_space_map *new_spaces,
6525  void (*destroy_space)(const char *context, int space))
6526 {
6527  struct parking_dp_spaces *old_range;
6528  struct parking_dp_spaces *new_range;
6529  int space;/*!< Current position in the current old range. */
6530  int stop;
6531 
6532  old_range = AST_LIST_FIRST(old_spaces);
6533  new_range = AST_LIST_FIRST(new_spaces);
6534  space = -1;
6535 
6536  while (old_range) {
6537  if (space < old_range->start) {
6538  space = old_range->start;
6539  }
6540  if (new_range) {
6541  if (space < new_range->start) {
6542  /* Current position in old range starts before new range. */
6543  if (old_range->stop < new_range->start) {
6544  /* Old range ends before new range. */
6545  stop = old_range->stop;
6546  old_range = AST_LIST_NEXT(old_range, node);
6547  } else {
6548  /* Tail of old range overlaps new range. */
6549  stop = new_range->start - 1;
6550  }
6551  } else if (/* new_range->start <= space && */ space <= new_range->stop) {
6552  /* Current position in old range overlaps new range. */
6553  if (old_range->stop <= new_range->stop) {
6554  /* Old range ends at or before new range. */
6555  old_range = AST_LIST_NEXT(old_range, node);
6556  } else {
6557  /* Old range extends beyond end of new range. */
6558  space = new_range->stop + 1;
6559  new_range = AST_LIST_NEXT(new_range, node);
6560  }
6561  continue;
6562  } else /* if (new_range->stop < space) */ {
6563  /* Current position in old range starts after new range. */
6564  new_range = AST_LIST_NEXT(new_range, node);
6565  continue;
6566  }
6567  } else {
6568  /* No more new ranges. All remaining old spaces are dead. */
6569  stop = old_range->stop;
6570  old_range = AST_LIST_NEXT(old_range, node);
6571  }
6572 
6573  /* Destroy dead parking spaces. */
6574  for (; space <= stop; ++space) {
6575  destroy_space(context, space);
6576  }
6577  }
6578 }
6579 
6580 /*!
6581  * \internal
6582  * \brief Remove unused parking lot context items.
6583  *
6584  * \param context Dialplan database context name.
6585  * \param old_ctx Before configuration reload context usage map.
6586  * \param new_ctx After configuration reload context usage map.
6587  *
6588  * \details
6589  * Remove context usage items that were in the old context but not in the
6590  * new context.
6591  *
6592  * \return Nothing
6593  */
6594 static void remove_dead_context_usage(const char *context, struct parking_dp_context *old_ctx, struct parking_dp_context *new_ctx)
6595 {
6596  remove_dead_ramp_usage(context, &old_ctx->access_extens, &new_ctx->access_extens);
6597  remove_dead_spaces_usage(context, &old_ctx->spaces, &new_ctx->spaces, destroy_space);
6598 #if 0
6599  /* I don't think we should destroy hints if the parking space still exists. */
6600  remove_dead_spaces_usage(context, &old_ctx->hints, &new_ctx->hints, destroy_space_hint);
6601 #endif
6602 }
6603 
6604 /*!
6605  * \internal
6606  * \brief Remove unused parking lot dialplan items.
6607  *
6608  * \param old_map Before configuration reload dialplan usage map.
6609  * \param new_map After configuration reload dialplan usage map.
6610  *
6611  * \details
6612  * Remove dialplan items that were in the old map but not in the
6613  * new map.
6614  *
6615  * \return Nothing
6616  */
6617 static void remove_dead_dialplan_useage(struct parking_dp_map *old_map, struct parking_dp_map *new_map)
6618 {
6619  struct parking_dp_context *old_ctx;
6620  struct parking_dp_context *new_ctx;
6621  struct ast_context *con;
6622  int cmp;
6623 
6624  old_ctx = AST_LIST_FIRST(old_map);
6625  new_ctx = AST_LIST_FIRST(new_map);
6626 
6627  while (new_ctx) {
6628  if (!old_ctx) {
6629  /* No old contexts left, so no dead stuff can remain. */
6630  return;
6631  }
6632  cmp = strcmp(old_ctx->context, new_ctx->context);
6633  if (cmp < 0) {
6634  /* New map does not have old map context. */
6635  con = ast_context_find(old_ctx->context);
6636  if (con) {
6638  }
6639  old_ctx = AST_LIST_NEXT(old_ctx, node);
6640  continue;
6641  }
6642  if (cmp == 0) {
6643  /* Old and new map have this context. */
6644  remove_dead_context_usage(old_ctx->context, old_ctx, new_ctx);
6645  old_ctx = AST_LIST_NEXT(old_ctx, node);
6646  } else {
6647  /* Old map does not have new map context. */
6648  }
6649  new_ctx = AST_LIST_NEXT(new_ctx, node);
6650  }
6651 
6652  /* Any old contexts left must be dead. */
6653  for (; old_ctx; old_ctx = AST_LIST_NEXT(old_ctx, node)) {
6654  con = ast_context_find(old_ctx->context);
6655  if (con) {
6657  }
6658  }
6659 }
6660 
6661 static int parkinglot_markall_cb(void *obj, void *arg, int flags)
6662 {
6663  struct ast_parkinglot *parkinglot = obj;
6664 
6665  parkinglot->the_mark = 1;
6666  return 0;
6667 }
6668 
6669 static int parkinglot_is_marked_cb(void *obj, void *arg, int flags)
6670 {
6671  struct ast_parkinglot *parkinglot = obj;
6672 
6673  if (parkinglot->the_mark) {
6674  if (AST_LIST_EMPTY(&parkinglot->parkings)) {
6675  /* This parking lot can actually be deleted. */
6676  return CMP_MATCH;
6677  }
6678  /* Try reloading later when parking lot is empty. */
6680  "Parking lot %s has parked calls. Could not remove.\n",
6681  parkinglot->name);
6682  parkinglot->disabled = 1;
6683  force_reload_load = 1;
6684  }
6685 
6686  return 0;
6687 }
6688 
6689 static int parkinglot_activate_cb(void *obj, void *arg, int flags)
6690 {
6691  struct ast_parkinglot *parkinglot = obj;
6692 
6693  if (parkinglot->the_mark) {
6694  /*
6695  * Don't activate a parking lot that still bears the_mark since
6696  * it is effectively deleted.
6697  */
6698  return 0;
6699  }
6700 
6701  if (parkinglot_activate(parkinglot)) {
6702  /*
6703  * The parking lot failed to activate. Allow reloading later to
6704  * see if that fixes it.
6705  */
6706  force_reload_load = 1;
6707  ast_log(LOG_WARNING, "Parking lot %s not open for business.\n", parkinglot->name);
6708  } else {
6709  ast_debug(1, "Parking lot %s now open for business. (parkpos %d-%d)\n",
6710  parkinglot->name, parkinglot->cfg.parking_start,
6711  parkinglot->cfg.parking_stop);
6712  }
6713 
6714  return 0;
6715 }
6716 
6717 static int load_config(int reload)
6718 {
6719  struct ast_flags config_flags = {
6720  reload && !force_reload_load ? CONFIG_FLAG_FILEUNCHANGED : 0 };
6721  struct ast_config *cfg;
6722  struct parking_dp_map old_usage_map = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6723  struct parking_dp_map new_usage_map = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6724 
6725  /* We are reloading now and have already determined if we will force the reload. */
6726  force_reload_load = 0;
6727 
6728  if (!default_parkinglot) {
6729  /* Must create the default default parking lot */
6731  if (!default_parkinglot) {
6732  ast_log(LOG_ERROR, "Configuration of default default parking lot failed.\n");
6733  return -1;
6734  }
6735  ast_debug(1, "Configuration of default default parking lot done.\n");
6736  }
6737 
6738  cfg = ast_config_load2("features.conf", "features", config_flags);
6739  if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
6740  /* No sense in asking for reload trouble if nothing changed. */
6741  ast_debug(1, "features.conf did not change.\n");
6742  return 0;
6743  }
6744  if (cfg == CONFIG_STATUS_FILEMISSING
6745  || cfg == CONFIG_STATUS_FILEINVALID) {
6746  ast_log(LOG_WARNING, "Could not load features.conf\n");
6747  return 0;
6748  }
6749 
6750  /* Save current parking lot dialplan needs. */
6751  if (build_dialplan_useage_map(&old_usage_map, 0)) {
6752  destroy_dialplan_usage_map(&old_usage_map);
6753 
6754  /* Allow reloading later to see if conditions have improved. */
6755  force_reload_load = 1;
6756  return -1;
6757  }
6758 
6760  "callback to mark all parking lots");
6761  process_config(cfg);
6762  ast_config_destroy(cfg);
6764  "callback to remove marked parking lots");
6765 
6766  /* Save updated parking lot dialplan needs. */
6767  if (build_dialplan_useage_map(&new_usage_map, 1)) {
6768  /*
6769  * Yuck, if this failure caused any parking lot dialplan items
6770  * to be lost, they will likely remain lost until Asterisk is
6771  * restarted.
6772  */
6773  destroy_dialplan_usage_map(&old_usage_map);
6774  destroy_dialplan_usage_map(&new_usage_map);
6775  return -1;
6776  }
6777 
6778  /* Remove no longer needed parking lot dialplan usage. */
6779  remove_dead_dialplan_useage(&old_usage_map, &new_usage_map);
6780 
6781  destroy_dialplan_usage_map(&old_usage_map);
6782  destroy_dialplan_usage_map(&new_usage_map);
6783 
6785  "callback to activate all parking lots");
6786 
6787  return 0;
6788 }
6789 
6790 /*!
6791  * \brief CLI command to list configured features
6792  * \param e
6793  * \param cmd
6794  * \param a
6795  *
6796  * \retval CLI_SUCCESS on success.
6797  * \retval NULL when tab completion is used.
6798  */
6799 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6800 {
6801  int i;
6802  struct ast_call_feature *feature;
6803  struct ao2_iterator iter;
6804  struct ast_parkinglot *curlot;
6805 #define HFS_FORMAT "%-25s %-7s %-7s\n"
6806 
6807  switch (cmd) {
6808 
6809  case CLI_INIT:
6810  e->command = "features show";
6811  e->usage =
6812  "Usage: features show\n"
6813  " Lists configured features\n";
6814  return NULL;
6815  case CLI_GENERATE:
6816  return NULL;
6817  }
6818 
6819  ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
6820  ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
6821 
6822  ast_cli(a->fd, HFS_FORMAT, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
6823 
6825  for (i = 0; i < FEATURES_COUNT; i++)
6826  ast_cli(a->fd, HFS_FORMAT, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
6828 
6829  ast_cli(a->fd, "\n");
6830  ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
6831  ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
6833  ast_cli(a->fd, "(none)\n");
6834  } else {
6836  AST_RWLIST_TRAVERSE(&feature_list, feature, feature_entry) {
6837  ast_cli(a->fd, HFS_FORMAT, feature->sname, "no def", feature->exten);
6838  }
6840  }
6841 
6842  ast_cli(a->fd, "\nFeature Groups:\n");
6843  ast_cli(a->fd, "---------------\n");
6845  ast_cli(a->fd, "(none)\n");
6846  } else {
6847  struct feature_group *fg;
6848  struct feature_group_exten *fge;
6849 
6851  AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
6852  ast_cli(a->fd, "===> Group: %s\n", fg->gname);
6853  AST_LIST_TRAVERSE(&fg->features, fge, entry) {
6854  ast_cli(a->fd, "===> --> %s (%s)\n", fge->feature->sname, fge->exten);
6855  }
6856  }
6858  }
6859 
6860  iter = ao2_iterator_init(parkinglots, 0);
6861  while ((curlot = ao2_iterator_next(&iter))) {
6862  ast_cli(a->fd, "\nCall parking (Parking lot: %s)\n", curlot->name);
6863  ast_cli(a->fd, "------------\n");
6864  ast_cli(a->fd,"%-22s: %s\n", "Parking extension", curlot->cfg.parkext);
6865  ast_cli(a->fd,"%-22s: %s\n", "Parking context", curlot->cfg.parking_con);
6866  ast_cli(a->fd,"%-22s: %d-%d\n", "Parked call extensions",
6867  curlot->cfg.parking_start, curlot->cfg.parking_stop);
6868  ast_cli(a->fd,"%-22s: %d ms\n", "Parkingtime", curlot->cfg.parkingtime);
6869  ast_cli(a->fd,"%-22s: %s\n", "MusicOnHold class", curlot->cfg.mohclass);
6870  ast_cli(a->fd,"%-22s: %s\n", "Enabled", AST_CLI_YESNO(!curlot->disabled));
6871  ast_cli(a->fd,"\n");
6872  ao2_ref(curlot, -1);
6873  }
6874  ao2_iterator_destroy(&iter);
6875 
6876  return CLI_SUCCESS;
6877 }
6878 
6880 {
6881  struct ast_context *con;
6882  int res;
6883 
6884  ast_mutex_lock(&features_reload_lock);/* Searialize reloading features.conf */
6885 
6886  /*
6887  * Always destroy the parking_con_dial context to remove buildup
6888  * of recalled extensions in the context. At worst, the parked
6889  * call gets hungup attempting to run an invalid extension when
6890  * we are trying to callback the parker or the preset return
6891  * extension. This is a small window of opportunity on an
6892  * execution chain that is not expected to happen very often.
6893  */
6895  if (con) {
6897  }
6898 
6899  res = load_config(1);
6901 
6902  return res;
6903 }
6904 
6905 static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6906 {
6907  switch (cmd) {
6908  case CLI_INIT:
6909  e->command = "features reload";
6910  e->usage =
6911  "Usage: features reload\n"
6912  " Reloads configured call features from features.conf\n";
6913  return NULL;
6914  case CLI_GENERATE:
6915  return NULL;
6916  }
6918 
6919  return CLI_SUCCESS;
6920 }
6921 
6922 /*!
6923  * \brief Actual bridge
6924  * \param chan
6925  * \param tmpchan
6926  *
6927  * Stop hold music, lock both channels, masq channels,
6928  * after bridge return channel to next priority.
6929  *
6930  * \retval 0 on success.
6931  * \retval -1 on error.
6932  */
6933 static int do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
6934 {
6935  const char *context;
6936  const char *exten;
6937  int priority;
6938 
6939  ast_moh_stop(chan);
6940  ast_channel_lock_both(chan, tmpchan);
6941  context = ast_strdupa(chan->context);
6942  exten = ast_strdupa(chan->exten);
6943  priority = chan->priority;
6944  ast_setstate(tmpchan, chan->_state);
6945  tmpchan->readformat = chan->readformat;
6946  tmpchan->writeformat = chan->writeformat;
6947  ast_channel_unlock(chan);
6948  ast_channel_unlock(tmpchan);
6949 
6950  /* Masquerade setup and execution must be done without any channel locks held */
6951  if (ast_channel_masquerade(tmpchan, chan)) {
6952  return -1;
6953  }
6954  ast_do_masquerade(tmpchan);
6955 
6956  /* when returning from bridge, the channel will continue at the next priority */
6957  ast_explicit_goto(tmpchan, context, exten, priority + 1);
6958 
6959  return 0;
6960 }
6961 
6962 /*!
6963  * \brief Bridge channels together
6964  * \param s
6965  * \param m
6966  *
6967  * Make sure valid channels were specified,
6968  * send errors if any of the channels could not be found/locked, answer channels if needed,
6969  * create the placeholder channels and grab the other channels
6970  * make the channels compatible, send error if we fail doing so
6971  * setup the bridge thread object and start the bridge.
6972  *
6973  * \retval 0
6974  */
6975 static int action_bridge(struct mansession *s, const struct message *m)
6976 {
6977  const char *channela = astman_get_header(m, "Channel1");
6978  const char *channelb = astman_get_header(m, "Channel2");
6979  const char *playtone = astman_get_header(m, "Tone");
6980  struct ast_channel *chana = NULL, *chanb = NULL, *chans[2];
6981  struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
6982  struct ast_bridge_thread_obj *tobj = NULL;
6983  char buf[256];
6984 
6985  /* make sure valid channels were specified */
6986  if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
6987  astman_send_error(s, m, "Missing channel parameter in request");
6988  return 0;
6989  }
6990 
6991  /* Start with chana */
6992  chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
6993  if (!chana) {
6994  snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
6995  astman_send_error(s, m, buf);
6996  return 0;
6997  }
6998 
6999  /* Answer the channels if needed */
7000  if (chana->_state != AST_STATE_UP)
7001  ast_answer(chana);
7002 
7003  /* create the placeholder channels and grab the other channels */
7004  if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
7005  NULL, NULL, chana->linkedid, 0, "Bridge/%s", chana->name))) {
7006  astman_send_error(s, m, "Unable to create temporary channel!");
7007  chana = ast_channel_unref(chana);
7008  return 0;
7009  }
7010 
7011  if (do_bridge_masquerade(chana, tmpchana)) {
7012  snprintf(buf, sizeof(buf), "Unable to masquerade channel %s!", channela);
7013  astman_send_error(s, m, buf);
7014  ast_hangup(tmpchana);
7015  chana = ast_channel_unref(chana);
7016  return 0;
7017  }
7018 
7019  chana = ast_channel_unref(chana);
7020 
7021  /* now do chanb */
7022  chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
7023  if (!chanb) {
7024  snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
7025  astman_send_error(s, m, buf);
7026  ast_hangup(tmpchana);
7027  return 0;
7028  }
7029 
7030  /* Answer the channels if needed */
7031  if (chanb->_state != AST_STATE_UP)
7032  ast_answer(chanb);
7033 
7034  /* create the placeholder channels and grab the other channels */
7035  if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
7036  NULL, NULL, chanb->linkedid, 0, "Bridge/%s", chanb->name))) {
7037  astman_send_error(s, m, "Unable to create temporary channels!");
7038  ast_hangup(tmpchana);
7039  chanb = ast_channel_unref(chanb);
7040  return 0;
7041  }
7042 
7043  if (do_bridge_masquerade(chanb, tmpchanb)) {
7044  snprintf(buf, sizeof(buf), "Unable to masquerade channel %s!", channelb);
7045  astman_send_error(s, m, buf);
7046  ast_hangup(tmpchana);
7047  ast_hangup(tmpchanb);
7048  chanb = ast_channel_unref(chanb);
7049  return 0;
7050  }
7051 
7052  chanb = ast_channel_unref(chanb);
7053 
7054  /* make the channels compatible, send error if we fail doing so */
7055  if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
7056  ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
7057  astman_send_error(s, m, "Could not make channels compatible for manager bridge");
7058  ast_hangup(tmpchana);
7059  ast_hangup(tmpchanb);
7060  return 0;
7061  }
7062 
7063  /* setup the bridge thread object and start the bridge */
7064  if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
7065  ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
7066  astman_send_error(s, m, "Unable to spawn a new bridge thread");
7067  ast_hangup(tmpchana);
7068  ast_hangup(tmpchanb);
7069  return 0;
7070  }
7071 
7072  tobj->chan = tmpchana;
7073  tobj->peer = tmpchanb;
7074  tobj->return_to_pbx = 1;
7075 
7076  if (ast_true(playtone)) {
7077  if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
7078  if (ast_waitstream(tmpchanb, "") < 0)
7079  ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
7080  }
7081  }
7082 
7083  chans[0] = tmpchana;
7084  chans[1] = tmpchanb;
7085 
7086  ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeAction", 2, chans,
7087  "Response: Success\r\n"
7088  "Channel1: %s\r\n"
7089  "Channel2: %s\r\n", tmpchana->name, tmpchanb->name);
7090 
7092 
7093  astman_send_ack(s, m, "Launched bridge thread with success");
7094 
7095  return 0;
7096 }
7097 
7098 /*!
7099  * \brief CLI command to list parked calls
7100  * \param e
7101  * \param cmd
7102  * \param a
7103  *
7104  * Check right usage, lock parking lot, display parked calls, unlock parking lot list.
7105  * \retval CLI_SUCCESS on success.
7106  * \retval CLI_SHOWUSAGE on incorrect number of arguments.
7107  * \retval NULL when tab completion is used.
7108  */
7109 static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7110 {
7111  struct parkeduser *cur;
7112  int numparked = 0;
7113  struct ao2_iterator iter;
7114  struct ast_parkinglot *curlot;
7115 
7116  switch (cmd) {
7117  case CLI_INIT:
7118  e->command = "parkedcalls show";
7119  e->usage =
7120  "Usage: parkedcalls show\n"
7121  " List currently parked calls\n";
7122  return NULL;
7123  case CLI_GENERATE:
7124  return NULL;
7125  }
7126 
7127  if (a->argc > e->args)
7128  return CLI_SHOWUSAGE;
7129 
7130  ast_cli(a->fd, "%-10s %-25s (%-15s %-12s %4s) %s\n", "Num", "Channel",
7131  "Context", "Extension", "Pri", "Timeout");
7132 
7133  iter = ao2_iterator_init(parkinglots, 0);
7134  while ((curlot = ao2_iterator_next(&iter))) {
7135  int lotparked = 0;
7136 
7137  /* subtract ref for iterator and for configured parking lot */
7138  ast_cli(a->fd, "*** Parking lot: %s (%d)\n", curlot->name,
7139  ao2_ref(curlot, 0) - 2 - (curlot == default_parkinglot));
7140 
7141  AST_LIST_LOCK(&curlot->parkings);
7142  AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
7143  ast_cli(a->fd, "%-10.10s %-25s (%-15s %-12s %4d) %6lds\n",
7144  cur->parkingexten, cur->chan->name, cur->context, cur->exten,
7145  cur->priority,
7146  (long) (cur->start.tv_sec + (cur->parkingtime / 1000) - time(NULL)));
7147  ++lotparked;
7148  }
7149  AST_LIST_UNLOCK(&curlot->parkings);
7150  if (lotparked) {
7151  numparked += lotparked;
7152  ast_cli(a->fd, " %d parked call%s in parking lot %s\n", lotparked,
7153  ESS(lotparked), curlot->name);
7154  }
7155 
7156  ao2_ref(curlot, -1);
7157  }
7158  ao2_iterator_destroy(&iter);
7159 
7160  ast_cli(a->fd, "---\n%d parked call%s in total.\n", numparked, ESS(numparked));
7161 
7162  return CLI_SUCCESS;
7163 }
7164 
7165 static struct ast_cli_entry cli_features[] = {
7166  AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
7167  AST_CLI_DEFINE(handle_features_reload, "Reloads configured features"),
7168  AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls"),
7169 };
7170 
7171 /*!
7172  * \brief Dump parking lot status
7173  * \param s
7174  * \param m
7175  *
7176  * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
7177  * \return Always RESULT_SUCCESS
7178  */
7179 static int manager_parking_status(struct mansession *s, const struct message *m)
7180 {
7181  struct parkeduser *cur;
7182  const char *id = astman_get_header(m, "ActionID");
7183  char idText[256] = "";
7184  struct ao2_iterator iter;
7185  struct ast_parkinglot *curlot;
7186  int numparked = 0;
7187 
7188  if (!ast_strlen_zero(id))
7189  snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
7190 
7191  astman_send_ack(s, m, "Parked calls will follow");
7192 
7193  iter = ao2_iterator_init(parkinglots, 0);
7194  while ((curlot = ao2_iterator_next(&iter))) {
7195  AST_LIST_LOCK(&curlot->parkings);
7196  AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
7197  astman_append(s, "Event: ParkedCall\r\n"
7198  "Parkinglot: %s\r\n"
7199  "Exten: %d\r\n"
7200  "Channel: %s\r\n"
7201  "From: %s\r\n"
7202  "Timeout: %ld\r\n"
7203  "CallerIDNum: %s\r\n"
7204  "CallerIDName: %s\r\n"
7205  "ConnectedLineNum: %s\r\n"
7206  "ConnectedLineName: %s\r\n"
7207  "%s"
7208  "\r\n",
7209  curlot->name,
7210  cur->parkingnum, cur->chan->name, cur->peername,
7211  (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
7212  S_COR(cur->chan->caller.id.number.valid, cur->chan->caller.id.number.str, ""), /* XXX in other places it is <unknown> */
7213  S_COR(cur->chan->caller.id.name.valid, cur->chan->caller.id.name.str, ""),
7214  S_COR(cur->chan->connected.id.number.valid, cur->chan->connected.id.number.str, ""), /* XXX in other places it is <unknown> */
7215  S_COR(cur->chan->connected.id.name.valid, cur->chan->connected.id.name.str, ""),
7216  idText);
7217  ++numparked;
7218  }
7219  AST_LIST_UNLOCK(&curlot->parkings);
7220  ao2_ref(curlot, -1);
7221  }
7222  ao2_iterator_destroy(&iter);
7223 
7224  astman_append(s,
7225  "Event: ParkedCallsComplete\r\n"
7226  "Total: %d\r\n"
7227  "%s"
7228  "\r\n",
7229  numparked, idText);
7230 
7231  return RESULT_SUCCESS;
7232 }
7233 
7234 /*!
7235  * \brief Create manager event for parked calls
7236  * \param s
7237  * \param m
7238  *
7239  * Get channels involved in park, create event.
7240  * \return Always 0
7241  *
7242  * \note ADSI is not compatible with this AMI action for the
7243  * same reason ch2 can no longer announce the parking space.
7244  */
7245 static int manager_park(struct mansession *s, const struct message *m)
7246 {
7247  const char *channel = astman_get_header(m, "Channel");
7248  const char *channel2 = astman_get_header(m, "Channel2");
7249  const char *timeout = astman_get_header(m, "Timeout");
7250  const char *parkinglotname = astman_get_header(m, "Parkinglot");
7251  char buf[BUFSIZ];
7252  int res = 0;
7253  struct ast_channel *ch1, *ch2;
7254  struct ast_park_call_args args = {
7255  /*
7256  * Don't say anything to ch2 since AMI is a third party parking
7257  * a call and we will likely crash if we do.
7258  *
7259  * XXX When the AMI action was originally implemented, the
7260  * parking space was announced to ch2. Unfortunately, grabbing
7261  * the ch2 lock and holding it while the announcement is played
7262  * was not really a good thing to do to begin with since it
7263  * could hold up the system. Also holding the lock is no longer
7264  * possible with a masquerade.
7265  *
7266  * Restoring the announcement to ch2 is not easily doable for
7267  * the following reasons:
7268  *
7269  * 1) The AMI manager is not the thread processing ch2.
7270  *
7271  * 2) ch2 could be the same as ch1, bridged to ch1, or some
7272  * random uninvolved channel.
7273  */
7275  };
7276 
7277  if (ast_strlen_zero(channel)) {
7278  astman_send_error(s, m, "Channel not specified");
7279  return 0;
7280  }
7281 
7282  if (ast_strlen_zero(channel2)) {
7283  astman_send_error(s, m, "Channel2 not specified");
7284  return 0;
7285  }
7286 
7287  if (!ast_strlen_zero(timeout)) {
7288  if (sscanf(timeout, "%30d", &args.timeout) != 1) {
7289  astman_send_error(s, m, "Invalid timeout value.");
7290  return 0;
7291  }
7292  }
7293 
7294  if (!(ch1 = ast_channel_get_by_name(channel))) {
7295  snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
7296  astman_send_error(s, m, buf);
7297  return 0;
7298  }
7299 
7300  if (!(ch2 = ast_channel_get_by_name(channel2))) {
7301  snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
7302  astman_send_error(s, m, buf);
7303  ast_channel_unref(ch1);
7304  return 0;
7305  }
7306 
7307  if (!ast_strlen_zero(parkinglotname)) {
7308  args.parkinglot = find_parkinglot(parkinglotname);
7309  }
7310 
7311  res = masq_park_call(ch1, ch2, &args);
7312  if (!res) {
7314  astman_send_ack(s, m, "Park successful");
7315  } else {
7316  astman_send_error(s, m, "Park failure");
7317  }
7318 
7319  if (args.parkinglot) {
7321  }
7322  ch1 = ast_channel_unref(ch1);
7323  ch2 = ast_channel_unref(ch2);
7324 
7325  return 0;
7326 }
7327 
7328 /*!
7329  * The presence of this datastore on the channel indicates that
7330  * someone is attemting to pickup or has picked up the channel.
7331  * The purpose is to prevent a race between two channels
7332  * attempting to pickup the same channel.
7333  */
7334 static const struct ast_datastore_info pickup_active = {
7335  .type = "pickup-active",
7336 };
7337 
7338 int ast_can_pickup(struct ast_channel *chan)
7339 {
7340  if (!chan->pbx && !chan->masq && !ast_test_flag(chan, AST_FLAG_ZOMBIE)
7341  && (chan->_state == AST_STATE_RINGING
7342  || chan->_state == AST_STATE_RING
7343  /*
7344  * Check the down state as well because some SIP devices do not
7345  * give 180 ringing when they can just give 183 session progress
7346  * instead. Issue 14005. (Some ISDN switches as well for that
7347  * matter.)
7348  */
7349  || chan->_state == AST_STATE_DOWN)
7350  && !ast_channel_datastore_find(chan, &pickup_active, NULL)) {
7351  return 1;
7352  }
7353  return 0;
7354 }
7355 
7356 static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
7357 {
7358  struct ast_channel *target = obj;/*!< Potential pickup target */
7359  struct ast_channel *chan = data;/*!< Channel wanting to pickup call */
7360 
7361  ast_channel_lock(target);
7362  if (chan != target && (chan->pickupgroup & target->callgroup)
7363  && ast_can_pickup(target)) {
7364  /* Return with the channel still locked on purpose */
7365  return CMP_MATCH | CMP_STOP;
7366  }
7367  ast_channel_unlock(target);
7368 
7369  return 0;
7370 }
7371 
7372 /*!
7373  * \brief Pickup a call
7374  * \param chan channel that initiated pickup.
7375  *
7376  * Walk list of channels, checking it is not itself, channel is pbx one,
7377  * check that the callgroup for both channels are the same and the channel is ringing.
7378  * Answer calling channel, flag channel as answered on queue, masq channels together.
7379  */
7380 int ast_pickup_call(struct ast_channel *chan)
7381 {
7382  struct ast_channel *target;/*!< Potential pickup target */
7383  int res = -1;
7384  ast_debug(1, "pickup attempt by %s\n", chan->name);
7385 
7386  /* The found channel is already locked. */
7387  target = ast_channel_callback(find_channel_by_group, NULL, chan, 0);
7388  if (target) {
7389  ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", target->name, chan->name);
7390 
7391  res = ast_do_pickup(chan, target);
7392  ast_channel_unlock(target);
7393  if (!res) {
7394  if (!ast_strlen_zero(pickupsound)) {
7395  pbx_builtin_setvar_helper(target, "BRIDGE_PLAY_SOUND", pickupsound);
7396  }
7397  } else {
7398  ast_log(LOG_WARNING, "pickup %s failed by %s\n", target->name, chan->name);
7399  }
7400  target = ast_channel_unref(target);
7401  }
7402 
7403  if (res < 0) {
7404  ast_debug(1, "No call pickup possible... for %s\n", chan->name);
7406  ast_answer(chan);
7408  }
7409  }
7410 
7411  return res;
7412 }
7413 
7414 int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
7415 {
7416  struct ast_party_connected_line connected_caller;
7417  struct ast_channel *chans[2] = { chan, target };
7418  struct ast_datastore *ds_pickup;
7419  const char *chan_name;/*!< A masquerade changes channel names. */
7420  const char *target_name;/*!< A masquerade changes channel names. */
7421  int res = -1;
7422 
7423  target_name = ast_strdupa(target->name);
7424  ast_debug(1, "Call pickup on '%s' by '%s'\n", target_name, chan->name);
7425 
7426  /* Mark the target to block any call pickup race. */
7427  ds_pickup = ast_datastore_alloc(&pickup_active, NULL);
7428  if (!ds_pickup) {
7430  "Unable to create channel datastore on '%s' for call pickup\n", target_name);
7431  return -1;
7432  }
7433  ast_channel_datastore_add(target, ds_pickup);
7434 
7435  ast_party_connected_line_init(&connected_caller);
7436  ast_party_connected_line_copy(&connected_caller, &target->connected);
7437  ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */
7439  if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
7440  ast_channel_update_connected_line(chan, &connected_caller, NULL);
7441  }
7442  ast_party_connected_line_free(&connected_caller);
7443 
7444  ast_channel_lock(chan);
7445  chan_name = ast_strdupa(chan->name);
7446  ast_connected_line_copy_from_caller(&connected_caller, &chan->caller);
7447  ast_channel_unlock(chan);
7449 
7450  ast_cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, chan);
7451 
7452  if (ast_answer(chan)) {
7453  ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name);
7454  goto pickup_failed;
7455  }
7456 
7458  ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name);
7459  goto pickup_failed;
7460  }
7461 
7462  ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
7463 
7464  /* setting this flag to generate a reason header in the cancel message to the ringing channel */
7466 
7467  if (ast_channel_masquerade(target, chan)) {
7468  ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan_name,
7469  target_name);
7470  goto pickup_failed;
7471  }
7472 
7473  /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */
7474  ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,
7475  "Channel: %s\r\n"
7476  "TargetChannel: %s\r\n",
7477  chan_name, target_name);
7478 
7479  /* Do the masquerade manually to make sure that it is completed. */
7480  ast_do_masquerade(target);
7481  res = 0;
7482 
7483 pickup_failed:
7484  ast_channel_lock(target);
7485  if (!ast_channel_datastore_remove(target, ds_pickup)) {
7486  ast_datastore_free(ds_pickup);
7487  }
7488  ast_party_connected_line_free(&connected_caller);
7489 
7490  return res;
7491 }
7492 
7493 static char *app_bridge = "Bridge";
7494 
7495 enum {
7497  OPT_CALLEE_HANGUP = (1 << 1),
7498  OPT_CALLER_HANGUP = (1 << 2),
7500  OPT_DURATION_STOP = (1 << 4),
7505  OPT_CALLEE_PARK = (1 << 9),
7506  OPT_CALLER_PARK = (1 << 10),
7507  OPT_CALLEE_KILL = (1 << 11),
7508 };
7509 
7510 enum {
7513  /* note: this entry _MUST_ be the last one in the enum */
7515 };
7516 
7531 
7533  char *parse, struct timeval *calldurationlimit)
7534 {
7535  char *stringp = ast_strdupa(parse);
7536  char *limit_str, *warning_str, *warnfreq_str;
7537  const char *var;
7538  int play_to_caller = 0, play_to_callee = 0;
7539  int delta;
7540 
7541  limit_str = strsep(&stringp, ":");
7542  warning_str = strsep(&stringp, ":");
7543  warnfreq_str = strsep(&stringp, ":");
7544 
7545  config->timelimit = atol(limit_str);
7546  if (warning_str)
7547  config->play_warning = atol(warning_str);
7548  if (warnfreq_str)
7549  config->warning_freq = atol(warnfreq_str);
7550 
7551  if (!config->timelimit) {
7552  ast_log(LOG_WARNING, "Bridge does not accept L(%s), hanging up.\n", limit_str);
7553  config->timelimit = config->play_warning = config->warning_freq = 0;
7554  config->warning_sound = NULL;
7555  return -1; /* error */
7556  } else if ( (delta = config->play_warning - config->timelimit) > 0) {
7557  int w = config->warning_freq;
7558 
7559  /*
7560  * If the first warning is requested _after_ the entire call
7561  * would end, and no warning frequency is requested, then turn
7562  * off the warning. If a warning frequency is requested, reduce
7563  * the 'first warning' time by that frequency until it falls
7564  * within the call's total time limit.
7565  *
7566  * Graphically:
7567  * timelim->| delta |<-playwarning
7568  * 0__________________|_________________|
7569  * | w | | | |
7570  *
7571  * so the number of intervals to cut is 1+(delta-1)/w
7572  */
7573  if (w == 0) {
7574  config->play_warning = 0;
7575  } else {
7576  config->play_warning -= w * ( 1 + (delta-1)/w );
7577  if (config->play_warning < 1)
7578  config->play_warning = config->warning_freq = 0;
7579  }
7580  }
7581 
7582  ast_channel_lock(chan);
7583 
7584  var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
7585  play_to_caller = var ? ast_true(var) : 1;
7586 
7587  var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
7588  play_to_callee = var ? ast_true(var) : 0;
7589 
7590  if (!play_to_caller && !play_to_callee)
7591  play_to_caller = 1;
7592 
7593  var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
7594  config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
7595 
7596  /* The code looking at config wants a NULL, not just "", to decide
7597  * that the message should not be played, so we replace "" with NULL.
7598  * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
7599  * not found.
7600  */
7601 
7602  var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
7603  config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
7604 
7605  var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
7606  config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
7607 
7608  ast_channel_unlock(chan);
7609 
7610  /* undo effect of S(x) in case they are both used */
7611  calldurationlimit->tv_sec = 0;
7612  calldurationlimit->tv_usec = 0;
7613 
7614  /* more efficient to do it like S(x) does since no advanced opts */
7615  if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
7616  calldurationlimit->tv_sec = config->timelimit / 1000;
7617  calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
7618  ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
7619  calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
7620  config->timelimit = play_to_caller = play_to_callee =
7621  config->play_warning = config->warning_freq = 0;
7622  } else {
7623  ast_verb(4, "Limit Data for this call:\n");
7624  ast_verb(4, "timelimit = %ld ms (%.3lf s)\n", config->timelimit, config->timelimit / 1000.0);
7625  ast_verb(4, "play_warning = %ld ms (%.3lf s)\n", config->play_warning, config->play_warning / 1000.0);
7626  ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
7627  ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
7628  ast_verb(4, "warning_freq = %ld ms (%.3lf s)\n", config->warning_freq, config->warning_freq / 1000.0);
7629  ast_verb(4, "start_sound = %s\n", S_OR(config->start_sound, ""));
7630  ast_verb(4, "warning_sound = %s\n", config->warning_sound);
7631  ast_verb(4, "end_sound = %s\n", S_OR(config->end_sound, ""));
7632  }
7633  if (play_to_caller)
7635  if (play_to_callee)
7637  return 0;
7638 }
7639 
7640 
7641 /*!
7642  * \brief Bridge channels
7643  * \param chan
7644  * \param data channel to bridge with.
7645  *
7646  * Split data, check we aren't bridging with ourself, check valid channel,
7647  * answer call if not already, check compatible channels, setup bridge config
7648  * now bridge call, if transferred party hangs up return to PBX extension.
7649  */
7650 static int bridge_exec(struct ast_channel *chan, const char *data)
7651 {
7652  struct ast_channel *current_dest_chan, *final_dest_chan, *chans[2];
7653  char *tmp_data = NULL;
7654  struct ast_flags opts = { 0, };
7655  struct ast_bridge_config bconfig = { { 0, }, };
7656  char *opt_args[OPT_ARG_ARRAY_SIZE];
7657  struct timeval calldurationlimit = { 0, };
7658 
7660  AST_APP_ARG(dest_chan);
7661  AST_APP_ARG(options);
7662  );
7663 
7664  if (ast_strlen_zero(data)) {
7665  ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
7666  return -1;
7667  }
7668 
7669  tmp_data = ast_strdupa(data);
7670  AST_STANDARD_APP_ARGS(args, tmp_data);
7671  if (!ast_strlen_zero(args.options))
7672  ast_app_parse_options(bridge_exec_options, &opts, opt_args, args.options);
7673 
7674  /* avoid bridge with ourselves */
7675  if (!strcmp(chan->name, args.dest_chan)) {
7676  ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
7677  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7678  "Response: Failed\r\n"
7679  "Reason: Unable to bridge channel to itself\r\n"
7680  "Channel1: %s\r\n"
7681  "Channel2: %s\r\n",
7682  chan->name, args.dest_chan);
7683  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
7684  return 0;
7685  }
7686 
7687  /* make sure we have a valid end point */
7688  if (!(current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
7689  strlen(args.dest_chan)))) {
7690  ast_log(LOG_WARNING, "Bridge failed because channel %s does not exist\n",
7691  args.dest_chan);
7692  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7693  "Response: Failed\r\n"
7694  "Reason: Channel2 does not exist\r\n"
7695  "Channel1: %s\r\n"
7696  "Channel2: %s\r\n", chan->name, args.dest_chan);
7697  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
7698  return 0;
7699  }
7700 
7701  /* try to allocate a place holder where current_dest_chan will be placed */
7702  if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
7703  NULL, NULL, current_dest_chan->linkedid, 0, "Bridge/%s", current_dest_chan->name))) {
7704  ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
7705  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7706  "Response: Failed\r\n"
7707  "Reason: Cannot create placeholder channel\r\n"
7708  "Channel1: %s\r\n"
7709  "Channel2: %s\r\n", chan->name, args.dest_chan);
7710  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
7711  ast_channel_unref(current_dest_chan);
7712  return 0;
7713  }
7714 
7715  if (ast_test_flag(&opts, OPT_DURATION_LIMIT)
7717  && ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) {
7718  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7719  "Response: Failed\r\n"
7720  "Reason: Cannot setup bridge time limit\r\n"
7721  "Channel1: %s\r\n"
7722  "Channel2: %s\r\n", chan->name, args.dest_chan);
7723  ast_hangup(final_dest_chan);
7724  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
7725  current_dest_chan = ast_channel_unref(current_dest_chan);
7726  goto done;
7727  }
7728 
7729  if (do_bridge_masquerade(current_dest_chan, final_dest_chan)) {
7730  ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
7731  "Response: Failed\r\n"
7732  "Reason: Cannot masquerade channels\r\n"
7733  "Channel1: %s\r\n"
7734  "Channel2: %s\r\n", chan->name, args.dest_chan);
7735  ast_hangup(final_dest_chan);
7736  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
7737  current_dest_chan = ast_channel_unref(current_dest_chan);
7738  goto done;
7739  }
7740 
7741  /* answer the channel if needed */
7742  if (final_dest_chan->_state != AST_STATE_UP) {
7743  ast_answer(final_dest_chan);
7744  }
7745 
7746  chans[0] = current_dest_chan;
7747  chans[1] = final_dest_chan;
7748 
7749  /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
7750  /* try to make compatible, send error if we fail */
7751  if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
7752  ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
7753  ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
7754  "Response: Failed\r\n"
7755  "Reason: Could not make channels compatible for bridge\r\n"
7756  "Channel1: %s\r\n"
7757  "Channel2: %s\r\n", chan->name, final_dest_chan->name);
7758 
7759  /* Maybe we should return this channel to the PBX? */
7760  ast_hangup(final_dest_chan);
7761 
7762  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
7763  current_dest_chan = ast_channel_unref(current_dest_chan);
7764  goto done;
7765  }
7766 
7767  /* Report that the bridge will be successfull */
7768  ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
7769  "Response: Success\r\n"
7770  "Channel1: %s\r\n"
7771  "Channel2: %s\r\n", chan->name, final_dest_chan->name);
7772 
7773  current_dest_chan = ast_channel_unref(current_dest_chan);
7774 
7775  /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */
7777  if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
7778  if (ast_waitstream(final_dest_chan, "") < 0)
7779  ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
7780  }
7781  }
7782 
7783  if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER))
7785  if (ast_test_flag(&opts, OPT_CALLER_TRANSFER))
7787  if (ast_test_flag(&opts, OPT_CALLEE_HANGUP))
7789  if (ast_test_flag(&opts, OPT_CALLER_HANGUP))
7791  if (ast_test_flag(&opts, OPT_CALLEE_MONITOR))
7793  if (ast_test_flag(&opts, OPT_CALLER_MONITOR))
7795  if (ast_test_flag(&opts, OPT_CALLEE_PARK))
7797  if (ast_test_flag(&opts, OPT_CALLER_PARK))
7799 
7800  /*
7801  * Don't let the after-bridge code run the h-exten. We want to
7802  * continue in the dialplan.
7803  */
7805  ast_bridge_call(chan, final_dest_chan, &bconfig);
7806 
7807  /* The bridge has ended, set BRIDGERESULT to SUCCESS. */
7808  pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
7809 
7810  /* If the other channel has not been hung up, return it to the PBX */
7811  if (!ast_check_hangup(final_dest_chan)) {
7812  if (!ast_test_flag(&opts, OPT_CALLEE_KILL)) {
7813  ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n",
7814  final_dest_chan->context, final_dest_chan->exten,
7815  final_dest_chan->priority, final_dest_chan->name);
7816 
7817  if (ast_pbx_start(final_dest_chan)) {
7818  ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
7819  ast_hangup(final_dest_chan);
7820  } else {
7821  ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
7822  }
7823  } else {
7824  ast_hangup(final_dest_chan);
7825  }
7826  } else {
7827  ast_debug(1, "chan %s was hungup\n", final_dest_chan->name);
7828  ast_hangup(final_dest_chan);
7829  }
7830 done:
7831  ast_free((char *) bconfig.warning_sound);
7832  ast_free((char *) bconfig.end_sound);
7833  ast_free((char *) bconfig.start_sound);
7834 
7835  return 0;
7836 }
7837 
7838 #if defined(TEST_FRAMEWORK)
7839 /*!
7840  * \internal
7841  * \brief Convert parking spaces map list to a comma separated string.
7842  *
7843  * \param str String buffer to fill.
7844  * \param spaces Parking spaces map list to convert.
7845  *
7846  * \return Nothing
7847  */
7848 static void create_spaces_str(struct ast_str **str, struct parking_dp_space_map *spaces)
7849 {
7850  const char *comma;
7851  struct parking_dp_spaces *cur;
7852 
7853  ast_str_reset(*str);
7854  comma = "";
7855  AST_LIST_TRAVERSE(spaces, cur, node) {
7856  if (cur->start == cur->stop) {
7857  ast_str_append(str, 0, "%s%d", comma, cur->start);
7858  } else {
7859  ast_str_append(str, 0, "%s%d-%d", comma, cur->start, cur->stop);
7860  }
7861  comma = ",";
7862  }
7863 }
7864 #endif /* defined(TEST_FRAMEWORK) */
7865 
7866 #if defined(TEST_FRAMEWORK)
7867 /*!
7868  * \internal
7869  * \brief Compare parking spaces map to what is expected.
7870  *
7871  * \param test Unit test context.
7872  * \param spaces Parking spaces map list to check.
7873  * \param expected String to compare with.
7874  * \param what What is being compared.
7875  *
7876  * \retval 0 successful compare.
7877  * \retval nonzero if failed to compare.
7878  */
7879 static int check_spaces(struct ast_test *test, struct parking_dp_space_map *spaces, const char *expected, const char *what)
7880 {
7881  int cmp;
7882  struct ast_str *str = ast_str_alloca(1024);
7883 
7884  create_spaces_str(&str, spaces);
7885  cmp = strcmp(expected, ast_str_buffer(str));
7886  if (cmp) {
7888  "Unexpected parking space map for %s. Expect:'%s' Got:'%s'\n",
7889  what, expected, ast_str_buffer(str));
7890  }
7891  return cmp;
7892 }
7893 #endif /* defined(TEST_FRAMEWORK) */
7894 
7895 #if defined(TEST_FRAMEWORK)
7896 /*!
7897  * \internal
7898  * \brief Add a dead space to the dead spaces list.
7899  *
7900  * \param context Dead spaces list ptr pretending to be a context name ptr.
7901  * \param space Dead space to add to the list.
7902  *
7903  * \return Nothing
7904  */
7905 static void test_add_dead_space(const char *context, int space)
7906 {
7907  struct parking_dp_space_map *dead_spaces = (struct parking_dp_space_map *) context;
7908 
7909  usage_context_add_spaces(dead_spaces, space, space, NULL, 0);
7910 }
7911 #endif /* defined(TEST_FRAMEWORK) */
7912 
7913 #if defined(TEST_FRAMEWORK)
7914 struct test_map {
7915  const char *ramp;
7916  int start;
7917  int stop;
7918  const char *expect;
7919 };
7920 
7921 /*!
7922  * \internal
7923  * \brief Build a parking lot dialplan usage test map from a table.
7924  *
7925  * \param test Unit test context.
7926  * \param lot Parking lot to use to build test usage map.
7927  * \param table_name Name of passed in table.
7928  * \param table Usage information to put in the usage map.
7929  * \param num_entries Number of entries in the table.
7930  *
7931  * \retval Created context node on success.
7932  * \retval NULL on error.
7933  */
7934 static struct parking_dp_context *test_build_maps(struct ast_test *test,
7935  struct ast_parkinglot *lot, const char *table_name, const struct test_map *table,
7936  size_t num_entries)
7937 {
7938  struct parking_dp_context *ctx_node;
7939  int cur_index = 0;
7940  char what[40];
7941 
7942  snprintf(what, sizeof(what), "%s[%d]", table_name, cur_index);
7943  ast_copy_string(lot->cfg.parkext, table->ramp, sizeof(lot->cfg.parkext));
7944  lot->cfg.parking_start = table->start;
7945  lot->cfg.parking_stop = table->stop;
7946  ctx_node = build_dialplan_useage_context(lot);
7947  if (!ctx_node) {
7948  ast_test_status_update(test, "Failed to create parking lot context map for %s\n",
7949  what);
7950  return NULL;
7951  }
7952  if (check_spaces(test, &ctx_node->spaces, table->expect, what)) {
7954  return NULL;
7955  }
7956  while (--num_entries) {
7957  ++cur_index;
7958  ++table;
7959  snprintf(what, sizeof(what), "%s[%d]", table_name, cur_index);
7960  ast_copy_string(lot->cfg.parkext, table->ramp, sizeof(lot->cfg.parkext));
7961  lot->cfg.parking_start = table->start;
7962  lot->cfg.parking_stop = table->stop;
7963  if (dialplan_usage_add_parkinglot_data(ctx_node, lot, 1)) {
7964  ast_test_status_update(test, "Failed to add parking lot data for %s\n", what);
7966  return NULL;
7967  }
7968  if (check_spaces(test, &ctx_node->spaces, table->expect, what)) {
7970  return NULL;
7971  }
7972  }
7973  return ctx_node;
7974 }
7975 
7976 static const struct test_map test_old_ctx[] = {
7977  /* The following order of building ctx is important to test adding items to the lists. */
7978  { "702", 14, 15, "14-15" },
7979  { "700", 10, 11, "10-11,14-15" },
7980  { "701", 18, 19, "10-11,14-15,18-19" },
7981  { "703", 12, 13, "10-15,18-19" },
7982  { "704", 16, 17, "10-19" },
7983 
7984  /* Parking ramp and space conflicts are intended with these lines. */
7985  { "704", 9, 19, "9-19" },
7986  { "704", 9, 20, "9-20" },
7987  { "704", 8, 21, "8-21" },
7988 
7989  /* Add more spaces to ctx to test removing dead parking spaces. */
7990  { "705", 23, 25, "8-21,23-25" },
7991  { "706", 28, 31, "8-21,23-25,28-31" },
7992  { "707", 33, 34, "8-21,23-25,28-31,33-34" },
7993  { "708", 38, 40, "8-21,23-25,28-31,33-34,38-40" },
7994  { "709", 42, 43, "8-21,23-25,28-31,33-34,38-40,42-43" },
7995 };
7996 
7997 static const struct test_map test_new_ctx[] = {
7998  { "702", 4, 5, "4-5" },
7999  { "704", 24, 26, "4-5,24-26" },
8000  { "709", 29, 30, "4-5,24-26,29-30" },
8001  { "710", 32, 35, "4-5,24-26,29-30,32-35" },
8002  { "711", 37, 39, "4-5,24-26,29-30,32-35,37-39" },
8003 };
8004 #endif /* defined(TEST_FRAMEWORK) */
8005 
8006 #if defined(TEST_FRAMEWORK)
8007 /*!
8008  * \internal
8009  * \brief Test parking dialplan usage map code.
8010  *
8011  * \param test Unit test context.
8012  *
8013  * \retval 0 on success.
8014  * \retval -1 on error.
8015  */
8016 static int test_dialplan_usage_map(struct ast_test *test)
8017 {
8018  struct parking_dp_context *old_ctx;
8019  struct parking_dp_context *new_ctx;
8020  struct ast_parkinglot *lot;
8021  struct parking_dp_spaces *spaces;
8022  struct parking_dp_space_map dead_spaces = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
8023  int res;
8024 
8025  ast_test_status_update(test, "Test parking dialplan usage map code\n");
8026 
8027  lot = create_parkinglot("test_lot");
8028  if (!lot) {
8029  return -1;
8030  }
8031  ast_copy_string(lot->cfg.parking_con, "test-ctx", sizeof(lot->cfg.parking_con));
8032  lot->cfg.parkext_exclusive = 1;
8033 
8035  "Build old_ctx map\n");
8036  ast_log(LOG_NOTICE, "6 Ramp and space conflict warnings are expected.\n");
8037  old_ctx = test_build_maps(test, lot, "test_old_ctx", test_old_ctx,
8038  ARRAY_LEN(test_old_ctx));
8039  if (!old_ctx) {
8040  ao2_ref(lot, -1);
8041  return -1;
8042  }
8043 
8044  ast_test_status_update(test, "Build new_ctx map\n");
8045  new_ctx = test_build_maps(test, lot, "test_new_ctx", test_new_ctx,
8046  ARRAY_LEN(test_new_ctx));
8047  if (!new_ctx) {
8048  res = -1;
8049  goto fail_old_ctx;
8050  }
8051 
8052  ast_test_status_update(test, "Test removing dead parking spaces\n");
8053  remove_dead_spaces_usage((void *) &dead_spaces, &old_ctx->spaces,
8054  &new_ctx->spaces, test_add_dead_space);
8055  if (check_spaces(test, &dead_spaces, "8-21,23,28,31,40,42-43", "dead_spaces")) {
8056  res = -1;
8057  goto fail_dead_spaces;
8058  }
8059 
8060  res = 0;
8061 
8062 fail_dead_spaces:
8063  while ((spaces = AST_LIST_REMOVE_HEAD(&dead_spaces, node))) {
8064  ast_free(spaces);
8065  }
8067 
8068 fail_old_ctx:
8070  ao2_ref(lot, -1);
8071  return res;
8072 }
8073 #endif /* defined(TEST_FRAMEWORK) */
8074 
8075 #if defined(TEST_FRAMEWORK)
8076 static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original)
8077 {
8078  return 0;
8079 }
8080 #endif /* defined(TEST_FRAMEWORK) */
8081 
8082 #if defined(TEST_FRAMEWORK)
8083 static struct ast_channel *create_test_channel(const struct ast_channel_tech *fake_tech)
8084 {
8085  struct ast_channel *test_channel1;
8086 
8087  if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
8088  NULL, NULL, 0, 0, "TestChannel1"))) {
8089  ast_log(LOG_WARNING, "Whoa, test channel creation failed.\n");
8090  return NULL;
8091  }
8092 
8093  /* normally this is done in the channel driver */
8094  test_channel1->nativeformats = AST_FORMAT_GSM;
8095  test_channel1->writeformat = AST_FORMAT_GSM;
8096  test_channel1->rawwriteformat = AST_FORMAT_GSM;
8097  test_channel1->readformat = AST_FORMAT_GSM;
8098  test_channel1->rawreadformat = AST_FORMAT_GSM;
8099  test_channel1->tech = fake_tech;
8100 
8101  return test_channel1;
8102 }
8103 #endif /* defined(TEST_FRAMEWORK) */
8104 
8105 #if defined(TEST_FRAMEWORK)
8106 static int unpark_test_channel(struct ast_channel *toremove, struct ast_park_call_args *args)
8107 {
8108  struct ast_context *con;
8109  struct parkeduser *pu_toremove;
8110  int res = 0;
8111 
8112  args->pu->notquiteyet = 1; /* go ahead and stop processing the test parking */
8113 
8114  AST_LIST_LOCK(&args->pu->parkinglot->parkings);
8115  AST_LIST_TRAVERSE_SAFE_BEGIN(&args->pu->parkinglot->parkings, pu_toremove, list) {
8116  if (pu_toremove == args->pu) {
8118  break;
8119  }
8120  }
8123 
8124  if (!pu_toremove) {
8125  ast_log(LOG_WARNING, "Whoa, could not find parking test call!\n");
8126  return -1;
8127  }
8128 
8129  con = ast_context_find(args->pu->parkinglot->cfg.parking_con);
8130  if (con) {
8131  if (ast_context_remove_extension2(con, args->pu->parkingexten, 1, NULL, 0)) {
8132  ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
8133  res = -1;
8134  } else {
8137  }
8138  } else {
8139  ast_log(LOG_WARNING, "Whoa, no parking context?\n");
8140  res = -1;
8141  }
8142 
8143  parkinglot_unref(pu_toremove->parkinglot);
8144  ast_free(pu_toremove);
8145  args->pu = NULL;
8146 
8147  if (!res && toremove) {
8148  ast_hangup(toremove);
8149  }
8150  return res;
8151 }
8152 #endif /* defined(TEST_FRAMEWORK) */
8153 
8154 #if defined(TEST_FRAMEWORK)
8155 AST_TEST_DEFINE(features_test)
8156 {
8157  struct ast_channel *test_channel1 = NULL;
8158  struct ast_channel *parked_chan = NULL;
8159  struct ast_parkinglot *dynlot;
8160  struct ast_park_call_args args = {
8162  };
8163 
8164  int res = 0;
8165 
8166  static const struct ast_channel_tech fake_tech = {
8167  .fixup = fake_fixup, /* silence warning from masquerade */
8168  };
8169 
8170  static const char unique_lot_1[] = "myuniquetestparkinglot314";
8171  static const char unique_lot_2[] = "myuniquetestparkinglot3141592654";
8172  static const char unique_context_1[] = "myuniquetestcontext314";
8173  static const char unique_context_2[] = "myuniquetestcontext3141592654";
8174  static const char parkinglot_parkext[] = "750";
8175  static const char parkinglot_range[] = "751-760";
8176 
8177  switch (cmd) {
8178  case TEST_INIT:
8179  info->name = "features_test";
8180  info->category = "/main/features/";
8181  info->summary = "Features unit test";
8182  info->description =
8183  "Tests whether parking respects PARKINGLOT settings";
8184  return AST_TEST_NOT_RUN;
8185  case TEST_EXECUTE:
8186  break;
8187  }
8188 
8189  if (test_dialplan_usage_map(test)) {
8190  res = -1;
8191  goto exit_features_test;
8192  }
8193 
8194  /* changing a config option is a bad practice, but must be done in this case */
8195  parkeddynamic = 1;
8196 
8197  ast_test_status_update(test, "Test parking functionality with defaults\n");
8198  if (!(test_channel1 = create_test_channel(&fake_tech))) {
8199  res = -1;
8200  goto exit_features_test;
8201  }
8202  if (park_call_full(test_channel1, NULL, &args)) {
8203  res = -1;
8204  goto exit_features_test;
8205  }
8206  if (unpark_test_channel(test_channel1, &args)) {
8207  res = -1;
8208  goto exit_features_test;
8209  }
8210 
8211 
8212  ast_test_status_update(test, "Check that certain parking options are respected\n");
8213  if (!(test_channel1 = create_test_channel(&fake_tech))) {
8214  res = -1;
8215  goto exit_features_test;
8216  }
8217  pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_lot_1);
8218  pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNCONTEXT", unique_context_1);
8219  pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNEXTEN", parkinglot_parkext);
8220  pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
8221  if (park_call_full(test_channel1, NULL, &args)) {
8222  res = -1;
8223  goto exit_features_test;
8224  }
8225  /* grab newly created parking lot for destruction in the end */
8226  dynlot = args.pu->parkinglot;
8227  if (args.pu->parkingnum != 751
8228  || strcmp(dynlot->name, unique_lot_1)
8229  || strcmp(dynlot->cfg.parking_con, unique_context_1)
8230  || strcmp(dynlot->cfg.parkext, parkinglot_parkext)
8231  || dynlot->cfg.parking_start != 751
8232  || dynlot->cfg.parking_stop != 760) {
8233  ast_test_status_update(test, "Parking settings were not respected\n");
8234  ast_test_status_update(test, "Dyn-name:%s\n", dynlot->name);
8235  ast_test_status_update(test, "Dyn-context:%s\n", dynlot->cfg.parking_con);
8236  ast_test_status_update(test, "Dyn-parkext:%s\n", dynlot->cfg.parkext);
8237  ast_test_status_update(test, "Dyn-parkpos:%d-%d\n", dynlot->cfg.parking_start,
8238  dynlot->cfg.parking_stop);
8239  ast_test_status_update(test, "Parked in space:%d\n", args.pu->parkingnum);
8240  if (!unpark_test_channel(test_channel1, &args)) {
8241  test_channel1 = NULL;
8242  }
8243  res = -1;
8244  goto exit_features_test;
8245  } else {
8246  ast_test_status_update(test, "Parking settings for non-masquerading park verified\n");
8247  }
8248  if (unpark_test_channel(test_channel1, &args)) {
8249  res = -1;
8250  goto exit_features_test;
8251  }
8252 
8253 
8254  ast_test_status_update(test, "Check #2 that certain parking options are respected\n");
8255  if (!(test_channel1 = create_test_channel(&fake_tech))) {
8256  res = -1;
8257  goto exit_features_test;
8258  }
8259  pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_lot_2);
8260  pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNCONTEXT", unique_context_2);
8261  pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNEXTEN", parkinglot_parkext);
8262  pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
8263  if (masq_park_call(test_channel1, NULL, &args)) {
8264  res = -1;
8265  goto exit_features_test;
8266  }
8267  /* hangup zombie channel */
8268  ast_hangup(test_channel1);
8269  test_channel1 = NULL;
8270 
8271  dynlot = args.pu->parkinglot;
8272  if (args.pu->parkingnum != 751
8273  || strcmp(dynlot->name, unique_lot_2)
8274  || strcmp(dynlot->cfg.parking_con, unique_context_2)
8275  || strcmp(dynlot->cfg.parkext, parkinglot_parkext)
8276  || dynlot->cfg.parking_start != 751
8277  || dynlot->cfg.parking_stop != 760) {
8278  ast_test_status_update(test, "Parking settings were not respected\n");
8279  ast_test_status_update(test, "Dyn-name:%s\n", dynlot->name);
8280  ast_test_status_update(test, "Dyn-context:%s\n", dynlot->cfg.parking_con);
8281  ast_test_status_update(test, "Dyn-parkext:%s\n", dynlot->cfg.parkext);
8282  ast_test_status_update(test, "Dyn-parkpos:%d-%d\n", dynlot->cfg.parking_start,
8283  dynlot->cfg.parking_stop);
8284  ast_test_status_update(test, "Parked in space:%d\n", args.pu->parkingnum);
8285  res = -1;
8286  } else {
8287  ast_test_status_update(test, "Parking settings for masquerading park verified\n");
8288  }
8289 
8290  /* find the real channel */
8291  parked_chan = ast_channel_get_by_name("TestChannel1");
8292  if (unpark_test_channel(parked_chan, &args)) {
8293  if (parked_chan) {
8294  ast_hangup(parked_chan);
8295  }
8296  res = -1;
8297  }
8298  parked_chan = ast_channel_unref(parked_chan);
8299 
8300 
8301 exit_features_test:
8302 
8303  if (test_channel1) {
8304  ast_hangup(test_channel1);
8305  }
8306 
8307  force_reload_load = 1;
8309  return res ? AST_TEST_FAIL : AST_TEST_PASS;
8310 }
8311 #endif /* defined(TEST_FRAMEWORK) */
8312 
8313 /*! \internal \brief Clean up resources on Asterisk shutdown */
8314 static void features_shutdown(void)
8315 {
8316  ast_cli_unregister_multiple(cli_features, ARRAY_LEN(cli_features));
8317  ast_devstate_prov_del("Park");
8318  ast_manager_unregister("Bridge");
8319  ast_manager_unregister("Park");
8320  ast_manager_unregister("Parkinglots");
8321  ast_manager_unregister("ParkedCalls");
8323  ast_unregister_application(parkedcall);
8324  ast_unregister_application(app_bridge);
8325 #if defined(TEST_FRAMEWORK)
8326  AST_TEST_UNREGISTER(features_test);
8327 #endif /* defined(TEST_FRAMEWORK) */
8328 
8329  pthread_cancel(parking_thread);
8330  pthread_kill(parking_thread, SIGURG);
8331  pthread_join(parking_thread, NULL);
8333  ao2_ref(parkinglots, -1);
8334 }
8335 
8337 {
8338  int res;
8339 
8341  if (!parkinglots) {
8342  return -1;
8343  }
8344 
8345  res = load_config(0);
8346  if (res) {
8347  return res;
8348  }
8349  ast_cli_register_multiple(cli_features, ARRAY_LEN(cli_features));
8351  return -1;
8352  }
8353  ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
8354  res = ast_register_application2(parkedcall, parked_call_exec, NULL, NULL, NULL);
8355  if (!res)
8356  res = ast_register_application2(parkcall, park_call_exec, NULL, NULL, NULL);
8357  if (!res) {
8361  }
8362 
8363  res |= ast_devstate_prov_add("Park", metermaidstate);
8364 #if defined(TEST_FRAMEWORK)
8365  res |= AST_TEST_REGISTER(features_test);
8366 #endif /* defined(TEST_FRAMEWORK) */
8367 
8369 
8370  return res;
8371 }
int parking_stop
Definition: features.c:501
const char * type
Definition: datastore.h:32
char exten[FEATURE_MAX_LEN]
Definition: features.h:69
struct ast_flags peer_features
Definition: features.c:653
static void * do_parking_thread(void *ignore)
Take care of parked calls and unpark them if needed.
Definition: features.c:4984
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
Definition: channel.c:3534
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
static int parkinglot_hash_cb(const void *obj, const int flags)
Definition: features.c:862
char context[AST_MAX_CONTEXT]
Definition: features.c:475
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
enum sip_cc_notify_state state
Definition: chan_sip.c:842
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2308
const ast_string_field gname
Definition: features.c:407
static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
Definition: features.c:1470
pthread_t thread
Definition: app_meetme.c:962
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Find devicestate as text message for output.
Definition: devicestate.c:215
#define ast_rwlock_rdlock(a)
Definition: lock.h:201
#define ast_channel_lock(chan)
Definition: channel.h:2466
void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
Simulate a DTMF end on a broken bridge channel.
Definition: features.c:3927
static struct ast_channel * feature_request_and_dial(struct ast_channel *caller, const char *caller_name, struct ast_channel *requestor, struct ast_channel *transferee, const char *type, format_t format, void *data, int timeout, int *outstate, const char *language)
Definition: features.c:3544
static void * dial_features_duplicate(void *data)
Definition: features.c:731
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_DEFINE_APP_ARGS_TYPE(type, arglist)
Define a structure type to hold an application&#39;s arguments.
Definition: app.h:588
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:114
static ast_rwlock_t features_lock
Definition: features.c:2979
static const char * parkedcall
Definition: features.c:419
Music on hold handling.
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
char * options
Definition: features.c:634
ast_device_state
Device States.
Definition: devicestate.h:51
long feature_timer
Definition: channel.h:980
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
static struct ast_parkinglot * parkinglot_addref(struct ast_parkinglot *parkinglot)
Definition: features.c:5435
feature_interpret_op
Definition: features.c:413
struct ast_channel * masq
Definition: channel.h:751
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
Definition: app.h:732
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
Definition: features.c:869
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
static int play_message_to_chans(struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
Definition: features.c:2059
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void process_applicationmap_line(struct ast_variable *var)
Definition: features.c:5768
static int parkinglot_markall_cb(void *obj, void *arg, int flags)
Definition: features.c:6661
static void parkinglot_destroy(void *obj)
Destroy a parking lot.
Definition: features.c:5445
const char *const type
Definition: channel.h:508
Asterisk locking-related definitions:
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
Asterisk main include file. File version handling, generic pbx functions.
void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1)
Definition: channel.c:2665
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:884
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
struct ast_channel * peer
Definition: features.c:858
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_OPTION_AUDIO_MODE
Definition: frame.h:453
int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
Present a dialtone and collect a certain length extension.
Definition: app.c:120
static int transferdigittimeout
Definition: features.c:614
#define AST_RWLOCK_DEFINE_STATIC(rwlock)
Definition: lock.h:549
void(* end_bridge_callback_data_fixup)(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
Definition: channel.h:993
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
Definition: app.h:712
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
static const char config[]
Definition: cdr_csv.c:57
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct ast_call_feature * find_dynamic_feature(const char *name)
find a call feature by name
Definition: features.c:3100
static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
Definition: features.c:7356
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:156
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
Definition: channel.c:1601
struct ast_frame ast_null_frame
Definition: frame.c:131
struct timeval feature_start_time
Definition: channel.h:979
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
Definition: features.c:2200
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
char * strsep(char **str, const char *delims)
#define AST_FEATURE_RETURN_SUCCESSBREAK
Definition: features.h:40
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
unsigned int parkaddhints
Definition: features.c:550
int priority
Definition: channel.h:841
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
struct ast_channel * chan
Definition: features.c:857
const ast_string_field uniqueid
Definition: channel.h:787
static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
exec an app by feature
Definition: features.c:3179
struct ast_flags features_callee
Definition: channel.h:976
static struct parkinglot_cfg parkinglot_cfg_default
Definition: features.c:5508
#define ast_strdup(a)
Definition: astmm.h:109
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
static void clear_dialed_interfaces(struct ast_channel *chan)
Definition: features.c:3911
char exten[AST_MAX_EXTENSION]
Definition: features.c:476
Definition: ast_expr2.c:325
format_t writeformat
Definition: channel.h:854
int visible_indication
Definition: channel.h:861
static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
Definition: features.c:2490
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:94
static int bridge_exec(struct ast_channel *chan, const char *data)
Bridge channels.
Definition: features.c:7650
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
#define AST_DIGIT_ANY
Definition: file.h:47
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define DEFAULT_PARK_TIME
Definition: features.c:383
static void features_shutdown(void)
Definition: features.c:8314
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation...
Definition: channel.c:2329
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void remove_dead_context_usage(const char *context, struct parking_dp_context *old_ctx, struct parking_dp_context *new_ctx)
Definition: features.c:6594
int option_debug
Definition: asterisk.c:182
static struct parking_dp_context * build_dialplan_useage_context(struct ast_parkinglot *lot)
Definition: features.c:6324
Device state management.
Support for translation of data formats. translate.c.
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
void ast_cdr_end(struct ast_cdr *cdr)
End a call.
Definition: cdr.c:933
#define MAX_MUSICCLASS
Definition: channel.h:139
Call Event Logging API.
static struct parking_dp_spaces * build_dialplan_useage_spaces(int start, int stop)
Definition: features.c:6168
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
void * ptr
Definition: frame.h:160
void * tech_pvt
Definition: channel.h:744
static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
Attended transfer.
Definition: features.c:2521
static struct ast_parkinglot * copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot)
Copy parkinglot and store it with new name.
Definition: features.c:5034
static void unmap_features(void)
Definition: features.c:3248
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
Definition: features.c:3897
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
struct feature_group::@266 features
int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield)
Append to CDR user field for channel (stored in CDR)
Definition: cdr.c:1069
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
#define ast_set_flag(p, flag)
Definition: utils.h:70
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
static int set_chan_app_data(struct ast_channel *chan, const char *src_app_data)
Definition: features.c:957
#define LOG_WARNING
Definition: logger.h:144
int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2)
Report a channel event.
Definition: cel.c:645
struct ast_cdr * next
Definition: cdr.h:132
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Audiohooks Architecture.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
static struct ast_cli_entry cli_features[]
Definition: features.c:7165
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
unsigned int the_mark
Definition: features.c:566
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:11141
a bridge is established
Definition: cel.h:62
static int park_call_exec(struct ast_channel *chan, const char *data)
Park a call.
Definition: features.c:5063
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Indicate that the connected line information has changed.
Definition: channel.c:9085
int lineno
Definition: config.h:87
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
Definition: features.c:2024
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:90
static unsigned int atxferloopdelay
Definition: features.c:620
static struct ast_parkinglot * default_parkinglot
Default parking lot.
Definition: features.c:582
static void remove_dead_ramp_usage(const char *context, struct parking_dp_ramp_map *old_ramps, struct parking_dp_ramp_map *new_ramps)
Definition: features.c:6453
#define AST_FRAME_DTMF
Definition: frame.h:128
#define ast_opt_end_cdr_before_h_exten
Definition: options.h:122
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
int ast_cdr_setaccount(struct ast_channel *chan, const char *account)
Set account code, will generate AMI event.
Definition: cdr.c:990
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
unsigned int flags
Definition: utils.h:201
#define AST_OPTION_DIGIT_DETECT
Definition: frame.h:508
#define MAX_DIAL_FEATURE_OPTIONS
Definition: features.c:393
static struct feature_group * find_group(const char *name)
Find a group by name.
Definition: features.c:3138
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
static char * handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to list configured features.
Definition: features.c:6799
#define var
Definition: ast_expr2f.c:606
static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
Definition: features.c:4703
globally accessible channel datastores
format_t rawwriteformat
Definition: channel.h:856
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
#define AST_OPTION_TDD
Definition: frame.h:445
char uniqueid[150]
Definition: cdr.h:121
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay...
Definition: adsi.c:76
Test Framework API.
static int monitor_ok
Definition: features.c:640
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
void ast_cdr_setdisposition(struct ast_cdr *cdr, long int disposition)
Set the disposition for a call.
Definition: cdr.c:847
static struct ast_app_option park_call_options[128]
Definition: features.c:5060
static char xferfailsound[256]
Definition: features.c:591
#define EVENT_FLAG_CALL
Definition: manager.h:72
void ast_unregister_feature(struct ast_call_feature *feature)
unregister feature from feature_set
Definition: features.c:3074
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
Definition: cli.h:146
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:389
struct ast_channel * chan
Definition: features.c:471
#define HFS_FORMAT
Structure for a data store type.
Definition: datastore.h:31
Configuration File Parser.
#define FEATURE_APP_LEN
Definition: features.h:31
char * str
Subscriber name (Malloced)
Definition: channel.h:214
int ast_say_digits(struct ast_channel *chan, int num, const char *ints, const char *lang)
says digits
Definition: channel.c:8409
unsigned int stop
Definition: app_meetme.c:969
static int parkedplay
Definition: features.c:587
int ast_features_init(void)
Definition: features.c:8336
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4447
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:275
const char * orig_chan_name
Definition: features.c:1144
static struct ast_app_option bridge_exec_options[128]
Definition: features.c:7530
static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
Play message to both caller and callee in bridged call, plays synchronously, autoservicing the other ...
Definition: features.c:2078
static int atxfernoanswertimeout
Definition: features.c:618
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition: app.c:343
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Bridge a call, optionally allowing redirection.
Definition: features.c:3960
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:11146
static ast_mutex_t features_reload_lock
Definition: features.c:610
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
int parkedcallreparking
Enable DTMF based parking on bridge when picking up parked calls.
Definition: features.c:523
#define FEATURE_MAX_LEN
Definition: features.h:30
static int finishup(struct ast_channel *chan)
Definition: features.c:1870
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:371
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
Definition: channel.c:1062
static void playtone(struct ast_channel *chan, int tone, int len)
int(* stop)(struct ast_channel *chan, int need_lock)
Definition: monitor.h:50
struct ast_flags my_features
Definition: features.c:651
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:235
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8708
static enum ast_device_state metermaidstate(const char *data)
metermaids callback from devicestate.c
Definition: features.c:1105
#define AST_OPTION_TONE_VERIFY
Definition: frame.h:441
static struct ast_app * stopmixmonitor_app
Definition: features.c:645
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define ast_assert(a)
Definition: utils.h:738
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_cdr * cdr
Definition: channel.h:766
#define ast_opt_transmit_silence
Definition: options.h:120
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
static const char * findparkinglotname(struct ast_channel *chan)
Find parking lot name from channel.
Definition: features.c:1082
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
format_t nativeformats
Definition: channel.h:852
#define ast_str_alloca(init_len)
Definition: strings.h:608
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
static struct ast_cdr * pick_unlocked_cdr(struct ast_cdr *cdr)
return the first unlocked cdr in a possible chain
Definition: features.c:3854
Structure for a data store object.
Definition: datastore.h:54
static int parkinglot_is_marked_cb(void *obj, void *arg, int flags)
Definition: features.c:6669
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2353
struct ast_frame * ast_frisolate(struct ast_frame *fr)
Makes a frame independent of any static storage.
Definition: frame.c:391
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
static int mixmonitor_ok
Definition: features.c:643
const char * str
Definition: app_jack.c:144
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
Run a connected line interception macro and update a channel&#39;s connected line information.
Definition: channel.c:9618
#define END_OPTIONS
Definition: app.h:663
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static struct adsi_event justify[]
Definition: app_adsiprog.c:105
#define DEFAULT_ATXFER_DROP_CALL
Definition: features.c:388
const char * data
Definition: channel.h:755
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: features.c:7380
static void parkinglot_unref(struct ast_parkinglot *parkinglot)
Unreference parkinglot object.
Definition: features.c:5428
static struct ast_exten * get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
Definition: features.c:823
int value
Definition: syslog.c:39
static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
Park call via masqueraded channel and announce parking spot on peer channel.
Definition: features.c:1726
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int ast_default_amaflags
Definition: cdr.c:59
ADSI Support (built upon Caller*ID)
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:841
const ast_string_field linkedid
Definition: channel.h:787
#define LOG_DEBUG
Definition: logger.h:122
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7795
char * return_con
Definition: features.c:634
int(*const fixup)(struct ast_channel *oldchan, struct ast_channel *newchan)
Fix up a channel: If a channel is consumed, this is called. Basically update any -&gt;owner links...
Definition: channel.h:579
#define ast_rwlock_unlock(a)
Definition: lock.h:200
const char * ext
Definition: http.c:112
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static struct ao2_container * hints
Definition: pbx.c:1314
format_t rawreadformat
Definition: channel.h:855
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
void ast_free_ptr(void *ptr)
static void dial_features_destroy(void *data)
Definition: features.c:744
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: config.c:2499
ast_group_t pickupgroup
Definition: channel.h:819
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
const char * appl
Definition: channel.h:754
#define AST_ALERT_FD
Definition: channel.h:163
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
const char * return_con
Definition: features.c:1145
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
ast_group_t callgroup
Definition: channel.h:818
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
support routing for one touch call parking
Definition: features.c:1976
static char parkingretdahdiring[3]
Definition: features.c:596
static struct ast_datastore_info channel_app_data_datastore
Definition: features.c:952
unsigned int is_invalid
Definition: features.c:552
int ast_features_reload(void)
Reload call features from features.conf.
Definition: features.c:6879
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:6114
static unsigned int atxferdropcall
Definition: features.c:619
struct parkeduser * pu
Definition: features.c:1150
Utility functions.
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1808
const char * start_sound
Definition: channel.h:986
int args
This gets set in ast_cli_register()
Definition: cli.h:179
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static void remove_exten_if_exist(const char *context, const char *exten, int priority)
Definition: features.c:6427
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:638
#define ast_manager_event(chan, category, event, contents,...)
Definition: manager.h:221
int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:1057
int priority
Definition: features.c:477
#define CONFIG_STATUS_FILEMISSING
Definition: config.h:50
int ast_masq_park_call(struct ast_channel *park_me, struct ast_channel *parker, int timeout, int *extout)
Park a call via a masqueraded channel.
Definition: features.c:1857
static void ast_unregister_groups(void)
Remove all feature groups in the list.
Definition: features.c:3114
void ast_register_feature(struct ast_call_feature *feature)
register new feature into feature_set
Definition: features.c:2994
unsigned int flags
Definition: channel.h:850
static void destroy_dialplan_usage_context(struct parking_dp_context *doomed)
Definition: features.c:6043
static char * table
Definition: cdr_odbc.c:50
#define FEATURES_COUNT
Definition: features.c:2977
unsigned int options_specified
Definition: features.c:482
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
char app[FEATURE_APP_LEN]
Definition: features.h:73
int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
Definition: cdr.c:883
int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
Bridge two channels together.
Definition: channel.c:7506
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:98
static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
Definition: features.c:3449
void ast_change_name(struct ast_channel *chan, const char *newname)
Change channel name.
Definition: channel.c:6229
long int amaflags
Definition: cdr.h:112
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:703
#define DEFAULT_PARK_EXTENSION
Definition: features.c:384
static void ast_unregister_features(void)
Remove all features in the list.
Definition: features.c:3088
int ast_channel_audiohook_count_by_source(struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
Find out how many audiohooks from a certain source exist on a given channel, regardless of status...
Definition: audiohook.c:791
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
Announce call parking by ADSI.
Definition: features.c:1063
char parking_con[AST_MAX_EXTENSION]
Definition: features.c:497
void ast_rdlock_call_features(void)
Definition: features.c:3150
static int do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
Actual bridge.
Definition: features.c:6933
Description of one parked call, added to a list while active, then removed. The list belongs to a par...
Definition: features.c:470
const char * value
Definition: config.h:79
static struct parkinglot_cfg parkinglot_cfg_default_default
Definition: features.c:5498
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:516
int macropriority
Definition: channel.h:842
static const char app[]
Definition: app_adsiprog.c:49
void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Queue a connected line update frame on a channel.
Definition: channel.c:9098
struct ast_channel * ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, format_t format, struct outgoing_helper *oh, int *outstate)
Forwards a call to a new channel specified by the original channel&#39;s call_forward str...
Definition: channel.c:5386
General Asterisk PBX channel definitions.
struct parking_dp_space_map hints
Definition: features.c:458
unsigned int parkext_exclusive
Definition: features.c:548
static const char *const mixmonitor_spy_type
int ast_raw_answer(struct ast_channel *chan, int cdr_answer)
Answer a channel.
Definition: channel.c:2930
int(*const hangup)(struct ast_channel *chan)
Hangup (and possibly destroy) the channel.
Definition: channel.h:545
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2707
#define AST_FEATURE_RETURN_HANGUP
Definition: features.h:39
static int parked_call_exec(struct ast_channel *chan, const char *data)
Pickup parked call.
Definition: features.c:5173
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
static char pickup_ext[AST_MAX_EXTENSION]
Definition: features.c:421
static struct feature_group * register_group(const char *fgname)
Add new feature group.
Definition: features.c:3015
static char pickupsound[256]
Definition: features.c:592
const int fd
Definition: cli.h:153
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:172
int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration)
Send a DTMF digit to a channel.
Definition: channel.c:4755
static struct parking_dp_ramp * build_dialplan_useage_ramp(const char *exten, int exclusive)
Definition: features.c:6087
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct ast_datastore_info dialed_interface_info
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
static struct ast_datastore_info pickup_active
Definition: features.c:7334
char app_args[FEATURE_APP_ARGS_LEN]
Definition: features.h:74
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:11326
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
int datalen
Definition: frame.h:148
void ast_cdr_answer(struct ast_cdr *cdr)
Answer a call.
Definition: cdr.c:737
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:220
bridge configuration
Definition: channel.h:974
void * end_bridge_callback_data
Definition: channel.h:989
All softhangup flags.
Definition: channel.h:1055
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
const char * end_sound
Definition: channel.h:985
char * fname
Definition: features.h:67
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:998
long int ast_random(void)
Definition: utils.c:1640
static void manage_parkinglot(struct ast_parkinglot *curlot, const struct pollfd *pfds, int nfds, struct pollfd **new_pfds, int *new_nfds, int *ms)
Run management on parkinglots, called once per parkinglot.
Definition: features.c:4940
#define ao2_lock(a)
Definition: astobj2.h:488
const ast_string_field parkinglot
Definition: channel.h:787
void ast_cdr_setanswer(struct ast_cdr *cdr, struct timeval t)
Set the answer time for a call.
Definition: cdr.c:834
static char * orig_exten(int fd, const char *chan, const char *data)
orginate from extension
static int parkeddynamic
Definition: features.c:588
#define AST_BRIDGE_DTMF_CHANNEL_1
Report DTMF on channel 1.
Definition: channel.h:1934
#define AST_GENERATOR_FD
Definition: channel.h:166
#define AST_FEATURE_RETURN_PASSDIGITS
Definition: features.h:43
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:88
struct ast_call_feature * feature
Definition: features.c:400
int parking_start
Definition: features.c:499
#define AST_FEATURE_RETURN_KEEPTRYING
Definition: features.h:46
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
make channels compatible
Definition: features.c:2466
const char * return_ext
Definition: features.c:1146
const char * name
Definition: config.h:77
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:92
void ast_channel_set_linkgroup(struct ast_channel *chan, struct ast_channel *peer)
propagate the linked id between chan and peer
Definition: channel.c:6387
const ast_string_field exten
Definition: features.c:399
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
char sending_dtmf_digit
Definition: channel.h:873
static pthread_t parking_thread
Definition: features.c:648
#define PRIORITY_HINT
Definition: pbx.h:53
static struct ast_datastore_info dial_features_info
Definition: features.c:752
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
static int parkinglot_activate(struct ast_parkinglot *parkinglot)
Definition: features.c:5640
static struct ast_app * monitor_app
Definition: features.c:639
a transfer occurs
Definition: cel.h:74
Structure to describe a channel &quot;technology&quot;, ie a channel driver See for examples: ...
Definition: channel.h:507
struct ast_cdr * ast_cdr_dup_unique_swap(struct ast_cdr *cdr)
Duplicate a record and increment the sequence number of the old record.
Definition: cdr.c:200
Core PBX routines and definitions.
static int force_reload_load
Definition: features.c:585
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1558
int ast_cdr_update(struct ast_channel *chan)
Update CDR on a channel.
Definition: cdr.c:1083
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
a channel is parked
Definition: cel.h:70
#define AST_OPTION_FAX_DETECT
Definition: frame.h:512
unsigned int disabled
Definition: features.c:568
Structure for parking lots which are put in a container.
Definition: features.c:556
struct ast_flags features_caller
Definition: channel.h:975
struct ast_channel * ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
Call a function with every active channel.
Definition: channel.c:1634
int fds[AST_MAX_FDS]
Definition: channel.h:829
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8309
static const char * real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
Find the context for the transfer.
Definition: features.c:2321
static void park_space_abort(struct parkeduser *pu)
Definition: features.c:1272
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:224
static int reload(void)
Definition: app_amd.c:497
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
struct timeval answer
Definition: cdr.h:102
int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected)
Parse connected line indication frame data.
Definition: channel.c:8886
static char parking_con_dial[]
Context for parking dialback to parker.
Definition: features.c:607
Responsible for call detail data.
Definition: cdr.h:82
#define DEFAULT_ATXFER_CALLBACK_RETRIES
Definition: features.c:390
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:96
static int usage_context_add_ramp(struct parking_dp_ramp_map *ramp_map, const char *exten, int exclusive, struct ast_parkinglot *lot, int complain)
Definition: features.c:6113
ast_control_frame_type
Internal control frame subtype field values.
Definition: frame.h:319
struct ast_channel_tech ast_kill_tech
Kill the channel channel driver technology descriptor.
Definition: channel.c:668
struct parking_dp_ramp_map access_extens
Definition: features.c:454
char moh_class[FEATURE_MOH_LEN]
Definition: features.h:75
a transfer occurs
Definition: cel.h:76
void ast_cdr_start(struct ast_cdr *cdr)
Start a call.
Definition: cdr.c:727
#define AST_OPTION_FLAG_REQUEST
Definition: frame.h:431
static char parkingretcidname[256]
Definition: features.c:595
#define LOG_ERROR
Definition: logger.h:155
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:120
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
static int feature_check(struct ast_channel *chan, struct ast_flags *features, char *code)
Check if a feature exists.
Definition: features.c:3440
struct parkeduser::@270 list
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
int64_t format_t
Definition: frame_defs.h:32
const char * file
Definition: config.h:85
static struct @350 args
static char * app_bridge
Definition: features.c:7493
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_OPTION_RELAXDTMF
Definition: frame.h:449
static unsigned int atxfercallbackretries
Definition: features.c:621
static int remap_feature(const char *name, const char *value)
Definition: features.c:3258
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
struct timeval sending_dtmf_tv
Definition: channel.h:874
struct parkinglot_cfg cfg
Definition: features.c:560
static struct parkeduser * park_space_reserve(struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
Definition: features.c:1299
const ast_string_field call_forward
Definition: channel.h:787
#define EVENT_FLAG_USER
Definition: manager.h:77
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_TIMING_FD
Definition: channel.h:164
void ast_cdr_detach(struct ast_cdr *cdr)
Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other...
Definition: cdr.c:1328
enum ast_channel_state _state
Definition: channel.h:839
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:909
static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
Definition: features.c:1891
static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
Definition: features.c:2307
Connected Line/Party information.
Definition: channel.h:401
const ast_string_field name
Definition: channel.h:787
static void check_goto_on_transfer(struct ast_channel *chan)
Check goto on transfer.
Definition: features.c:896
static void remove_dead_spaces_usage(const char *context, struct parking_dp_space_map *old_spaces, struct parking_dp_space_map *new_spaces, void(*destroy_space)(const char *context, int space))
Definition: features.c:6523
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *flags)
Definition: cdr.c:1192
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static void * bridge_call_thread(void *data)
bridge the call
Definition: features.c:987
int _softhangup
Definition: channel.h:832
static char * handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: features.c:6905
static int dialplan_usage_add_parkinglot(struct parking_dp_map *usage_map, struct ast_parkinglot *lot, int complain)
Definition: features.c:6351
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define LOG_NOTICE
Definition: logger.h:133
static void remove_dead_dialplan_useage(struct parking_dp_map *old_map, struct parking_dp_map *new_map)
Definition: features.c:6617
int next_parking_space
Definition: features.c:563
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
#define AST_FEATURE_RETURN_STOREDIGITS
Definition: features.h:44
static char parkingretalertinfo[256]
Definition: features.c:597
int fdno
Definition: channel.h:834
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
char default_exten[FEATURE_MAX_LEN]
Definition: features.h:70
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
Definition: channel.c:8355
static char courtesytone[256]
Definition: features.c:589
struct timeval start
Definition: cdr.h:100
#define ESS(x)
Definition: cli.h:58
int errno
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static const char name[]
#define AST_MAX_CONTEXT
Definition: channel.h:136
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
Pickup a call target.
Definition: features.c:7414
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:611
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
Definition: channel.c:6241
int source
Information about the source of an update.
Definition: channel.h:424
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:418
char macrocontext[AST_MAX_CONTEXT]
Definition: channel.h:870
static char xfersound[256]
Definition: features.c:590
#define AST_CHANNEL_NAME
Definition: channel.h:137
static int add_features_datastore(struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
Definition: features.c:768
char parkext[AST_MAX_EXTENSION]
Definition: features.c:495
static struct ast_parkinglot * create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
Definition: features.c:1165
#define AST_MAX_FDS
Definition: channel.h:158
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1370
#define AST_FLAGS_ALL
Definition: utils.h:196
struct timeval start
Definition: features.c:472
static int process_config(struct ast_config *cfg)
Definition: features.c:5867
int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
Definition: cdr.c:383
static void destroy_dialplan_usage_map(struct parking_dp_map *doomed)
Definition: features.c:6068
static int featuredigittimeout
Definition: features.c:615
int stacklen
Definition: extconf.h:234
enum ast_control_frame_type hold_method
Definition: features.c:480
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
static void post_manager_event(const char *s, struct parkeduser *pu)
Output parking event to manager.
Definition: features.c:4629
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:829
char sname[FEATURE_SNAME_LEN]
Definition: features.h:68
int ast_call(struct ast_channel *chan, char *addr, int timeout)
Make a call.
Definition: channel.c:5761
static char * registrar
Definition: features.c:623
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:156
static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
store context, extension and priority
Definition: features.c:881
static int stopmixmonitor_ok
Definition: features.c:646
unsigned int inheritance
Definition: datastore.h:58
struct ast_parkinglot * parkinglot
Parkinglot to be parked in.
Definition: features.c:1152
#define FEATURE_SNAME_LEN
Definition: features.h:33
static struct ast_call_feature builtin_features[]
Definition: features.c:2981
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
static void destroy_space(const char *context, int space)
Definition: features.c:6498
static struct ast_parkinglot * create_parkinglot(const char *name)
Allocate parking lot structure.
Definition: features.c:5459
static const char type[]
Definition: chan_nbs.c:57
static int action_bridge(struct mansession *s, const struct message *m)
Bridge channels together.
Definition: features.c:6975
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
int ast_autoservice_ignore(struct ast_channel *chan, enum ast_frame_type ftype)
Ignore certain frame types.
Definition: autoservice.c:307
Structure used to handle boolean flags.
Definition: utils.h:200
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:251
static int parkinglot_activate_cb(void *obj, void *arg, int flags)
Definition: features.c:6689
#define ast_clear_flag(p, flag)
Definition: utils.h:77
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2631
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
Launch a new extension (i.e. new stack)
Definition: pbx.c:5425
uint8_t data[0]
Definition: frame.h:545
unsigned int parkfindnext
Definition: features.c:546
static void parkinglot_feature_flag_cfg(const char *pl_name, int *param, struct ast_variable *var)
Definition: features.c:5523
const char * usage
Definition: cli.h:171
#define FEATURE_SENSE_PEER
Definition: features.h:50
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
static int manager_park(struct mansession *s, const struct message *m)
Create manager event for parked calls.
Definition: features.c:7245
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
int parkedcallrecording
Enable DTMF based recording on a bridge when picking up parked calls.
Definition: features.c:543
#define ast_rwlock_wrlock(a)
Definition: lock.h:202
struct ast_parkinglot::parkinglot_parklist parkings
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
int parkedcalltransfers
Enable DTMF based transfers on bridge when picking up parked calls.
Definition: features.c:513
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2473
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:436
#define CLI_SUCCESS
Definition: cli.h:43
#define LOG_DTMF
Definition: logger.h:177
static int adsipark
Definition: features.c:612
char parkingexten[AST_MAX_EXTENSION]
Definition: features.c:474
void * data
Definition: datastore.h:56
#define FEATURE_MOH_LEN
Definition: features.h:35
static int parkinglot_config_read(const char *pl_name, struct parkinglot_cfg *cfg, struct ast_variable *var)
Definition: features.c:5546
#define DEFAULT_PARKINGLOT
Definition: features.h:37
void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1)
Definition: channel.c:2688
void ast_cdr_discard(struct ast_cdr *cdr)
Discard and free a CDR record.
Definition: cdr.c:488
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:666
static struct ast_app * mixmonitor_app
Definition: features.c:642
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
Definition: channel.c:2316
struct feature_group_exten::@264 entry
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:8691
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
Makes two channel formats compatible.
Definition: channel.c:5970
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
Standard Command Line Interface.
int parkedcallhangup
Enable DTMF based hangup on a bridge when pickup up parked calls.
Definition: features.c:533
format_t readformat
Definition: channel.h:853
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
ast_feature_operation operation
Definition: features.h:71
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8443
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
struct ast_parkinglot * parkinglot
Definition: features.c:486
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
ast_app: A registered application
Definition: pbx.c:971
static int usage_context_add_spaces(struct parking_dp_space_map *space_map, int start, int stop, struct ast_parkinglot *lot, int complain)
Definition: features.c:6194
char * pl_name
Definition: features.c:634
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
#define ast_realloc(a, b)
Definition: astmm.h:103
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
static char pickupfailsound[256]
Definition: features.c:593
Channel monitoring.
#define FEATURE_APP_ARGS_LEN
Definition: features.h:32
char * return_pri
Definition: features.c:634
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
#define DEFAULT_FEATURE_DIGIT_TIMEOUT
Definition: features.c:386
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:8731
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
Blind transfer user to another extension.
Definition: features.c:2350
int ast_park_call(struct ast_channel *park_me, struct ast_channel *parker, int timeout, const char *park_exten, int *extout)
Park a call and read back parked location.
Definition: features.c:1706
channel out of the park
Definition: cel.h:72
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define AST_CAUSE_BUSY
Definition: causes.h:148
int ast_is_deferrable_frame(const struct ast_frame *frame)
Should we keep this frame for later?
Definition: channel.c:1818
const ast_string_field accountcode
Definition: channel.h:787
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
This functionc locks given context, search for the right extension and fires out all peer in this ext...
Definition: pbx.c:6144
Data structure associated with a single frame of data.
Definition: frame.h:142
#define DEFAULT_ATXFER_LOOP_DELAY
Definition: features.c:389
int hangupcause
Definition: channel.h:849
static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
Monitor a channel by DTMF.
Definition: features.c:2098
Internal Asterisk hangup causes.
#define ast_manager_event_multichan(category, event, nchans, chans, contents,...)
Definition: manager.h:226
char name[AST_MAX_CONTEXT]
Definition: features.c:558
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context (or ANY context if NULL)
Definition: pbx.c:9875
static struct ast_parkinglot * find_parkinglot(const char *name)
Find parkinglot by name.
Definition: features.c:5017
#define AST_FEATURE_RETURN_SUCCESS
Definition: features.h:45
#define AST_TEST_DEFINE(hdr)
Definition: test.h:126
static int load_config(int reload)
Definition: features.c:6717
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition: pbx.c:6344
int ast_masq_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
Park a call via a masqueraded channel.
Definition: features.c:1803
static struct ao2_container * parkinglots
The configured parking lots container. Always at least one - the default parking lot.
Definition: features.c:575
#define FEATURE_EXTEN_LEN
Definition: features.h:34
char * timeout
Definition: features.c:634
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:870
static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
Definition: features.c:3865
static int manager_parking_status(struct mansession *s, const struct message *m)
Dump parking lot status.
Definition: features.c:7179
static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf, struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
Helper function for feature_interpret and ast_feature_detect.
Definition: features.c:3286
#define LOG_VERBOSE
Definition: logger.h:166
int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
Determine if parking extension exists in a given context.
Definition: features.c:844
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
enum ast_frame_type frametype
Definition: frame.h:144
struct ast_variable * next
Definition: config.h:82
static char * callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
Definition: features.c:4651
const char * warning_sound
Definition: channel.h:984
static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
Add feature to group.
Definition: features.c:3046
static int build_dialplan_useage_map(struct parking_dp_map *usage_map, int complain)
Definition: features.c:6396
struct ast_bridge_config bconfig
Definition: features.c:856
static char * handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to list parked calls.
Definition: features.c:7109
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: pbx.c:3013
#define AST_CLI_YESNO(x)
return Yes or No depending on the argument. This is used in many places in CLI command, having a function to generate this helps maintaining a consistent output (and possibly emitting the output in other languages, at some point).
Definition: cli.h:65
long int disposition
Definition: cdr.h:110
#define ast_frfree(fr)
Definition: frame.h:583
static struct ast_parkinglot * build_parkinglot(const char *pl_name, struct ast_variable *var)
Build parkinglot from configuration and chain it in if it doesn&#39;t already exist.
Definition: features.c:5689
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
Notify metermaids that we&#39;ve changed an extension.
Definition: features.c:1096
unsigned int exclusive
Definition: features.c:428
ast_park_call_options
Definition: features.c:1125
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
int parkingnum
Definition: features.c:473
#define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER
Definition: features.c:387
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send DTMF to a channel.
Definition: app.c:501
struct ast_channel_monitor * monitor
Definition: channel.h:769
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:7726
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:584
static const char * parkcall
Definition: features.c:637
int ast_adsi_unload_session(struct ast_channel *chan)
Definition: adsi.c:87
void(* end_bridge_callback)(void *)
Definition: channel.h:988
void ast_channel_log(char *title, struct ast_channel *chan)
Definition: features.c:3832
#define strdup(a)
Definition: astmm.h:106
void ast_unlock_call_features(void)
Definition: features.c:3155
struct parking_dp_space_map spaces
Definition: features.c:456
int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to the head of a channel&#39;s frame queue.
Definition: channel.c:1563
Say numbers and dates (maybe words one day too)
static void park_add_hints(const char *context, int start, int stop)
Add parking hints for all defined parking spaces.
Definition: features.c:5484
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
#define RESULT_SUCCESS
Definition: cli.h:39
#define ast_malloc(a)
Definition: astmm.h:91
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
Asterisk module definitions.
#define DEFAULT_TRANSFER_DIGIT_TIMEOUT
Definition: features.c:385
int amaflags
Definition: channel.h:843
char peername[AST_CHANNEL_NAME]
Definition: features.c:483
unsigned int return_to_pbx
Definition: features.c:859
struct ast_channel * ast_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *status)
Requests a channel.
Definition: channel.c:5695
int ast_app_exec_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char *macro_args)
Run a macro on a channel, placing an optional second channel into autoservice.
Definition: app.c:254
static snd_pcm_format_t format
Definition: chan_alsa.c:93
union ast_frame::@172 data
struct ast_channel_tech * tech
Definition: channel.h:743
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
#define ADSI_JUST_CENT
Definition: adsi.h:114
struct ast_call_feature::@170 feature_entry
static int dialplan_usage_add_parkinglot_data(struct parking_dp_context *ctx_node, struct ast_parkinglot *lot, int complain)
Definition: features.c:6297
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
unsigned char moh_trys
Definition: features.c:484
ast_context: An extension context
Definition: pbx.c:955
void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan)
Set the destination channel, if there was one.
Definition: cdr.c:812
unsigned int notquiteyet
Definition: features.c:481
a directed pickup was performed on this channel
Definition: cel.h:96
#define AST_FORMAT_GSM
Definition: frame.h:244
char exten[1]
Definition: features.c:430
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
int parkingtime
Definition: features.c:478
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2599
void * generatordata
Definition: channel.h:746
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
Definition: cdr.c:897
const ast_string_field language
Definition: channel.h:787
void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Set the connected line information in the Asterisk channel.
Definition: channel.c:8458
#define AST_CAUSE_CONGESTION
Definition: causes.h:152
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2971
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:499
static void bridge_call_thread_launch(struct ast_bridge_thread_obj *data)
create thread for the parked call
Definition: features.c:1037
#define AST_BRIDGE_DTMF_CHANNEL_0
Report DTMF on channel 0.
Definition: channel.h:1932
int ast_do_masquerade(struct ast_channel *chan)
Start masquerading a channel.
Definition: channel.c:6546
int ast_channel_audiohook_count_by_source_running(struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
Find out how many spies of a certain type exist on a given channel, and are in state running...
Definition: audiohook.c:830
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
const char * ast_pickup_ext(void)
Determine system call pickup extension.
Definition: features.c:849
struct ast_call_feature * ast_find_call_feature(const char *name)
look for a call feature entry by its sname
Definition: features.c:3160
#define FEATURE_SENSE_CHAN
Definition: features.h:49
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:989
#define BEGIN_OPTIONS
Definition: app.h:662
static int comebacktoorigin
Definition: features.c:616
int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature)
detect a feature before bridging
Definition: features.c:3434
a bridge is torn down
Definition: cel.h:64
int ast_manager_unregister(char *action)
Unregister a registered manager command.
Definition: manager.c:5355
jack_status_t status
Definition: app_jack.c:143
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
char * return_ext
Definition: features.c:634
int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame)
Run a redirecting interception macro and update a channel&#39;s redirecting information.
Definition: channel.c:9663
char mohclass[MAX_MUSICCLASS]
Definition: features.c:493
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
Definition: app.h:721
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:125
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
#define ast_mutex_unlock(a)
Definition: lock.h:156
static void set_peers(struct ast_channel **caller, struct ast_channel **callee, struct ast_channel *peer, struct ast_channel *chan, int sense)
set caller and callee according to the direction
Definition: features.c:1951
struct ast_pbx * pbx
Definition: channel.h:761
int ast_adsi_print(struct ast_channel *chan, char **lines, int *align, int voice)
Display some stuff on the screen.
Definition: adsi.c:65
int ast_bridge_timelimit(struct ast_channel *chan, struct ast_bridge_config *config, char *parse, struct timeval *calldurationlimit)
parse L option and read associated channel variables to set warning, warning frequency, and timelimit
Definition: features.c:7532
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
int ast_can_pickup(struct ast_channel *chan)
Test if a channel can be picked up.
Definition: features.c:7338
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
int ast_park_call_exten(struct ast_channel *park_me, struct ast_channel *parker, const char *park_exten, const char *park_context, int timeout, int *extout)
Park a call and read back parked location.
Definition: features.c:1655
static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense)
Check the dynamic features.
Definition: features.c:3403