Add the ability to dynamically specify weights for responses to DUNDi queries.
[asterisk/asterisk.git] / main / dial.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2007, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@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 Dialing API
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/time.h>
34 #include <signal.h>
35 #include <errno.h>
36 #include <unistd.h>
37
38 #include "asterisk/logger.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/options.h"
41 #include "asterisk/utils.h"
42 #include "asterisk/lock.h"
43 #include "asterisk/linkedlists.h"
44 #include "asterisk/dial.h"
45 #include "asterisk/pbx.h"
46
47 /*! \brief Main dialing structure. Contains global options, channels being dialed, and more! */
48 struct ast_dial {
49         int num;                                           /*! Current number to give to next dialed channel */
50         enum ast_dial_result state;                       /*! Status of dial */
51         void *options[AST_DIAL_OPTION_MAX];                /*! Global options */
52         ast_dial_state_callback state_callback;          /*! Status callback */
53         AST_LIST_HEAD_NOLOCK(, ast_dial_channel) channels; /*! Channels being dialed */
54         pthread_t thread;                                  /*! Thread (if running in async) */
55 };
56
57 /*! \brief Dialing channel structure. Contains per-channel dialing options, asterisk channel, and more! */
58 struct ast_dial_channel {
59         int num;                               /*! Unique number for dialed channel */
60         const char *tech;                      /*! Technology being dialed */
61         const char *device;                    /*! Device being dialed */
62         void *options[AST_DIAL_OPTION_MAX];    /*! Channel specific options */
63         int cause;                             /*! Cause code in case of failure */
64         struct ast_channel *owner;             /*! Asterisk channel */
65         AST_LIST_ENTRY(ast_dial_channel) list; /*! Linked list information */
66 };
67
68 /*! \brief Typedef for dial option enable */
69 typedef void *(*ast_dial_option_cb_enable)(void *data);
70
71 /*! \brief Typedef for dial option disable */
72 typedef int (*ast_dial_option_cb_disable)(void *data);
73
74 /* Structure for 'ANSWER_EXEC' option */
75 struct answer_exec_struct {
76         char app[AST_MAX_APP]; /* Application name */
77         char *args;            /* Application arguments */
78 };
79
80 /* Enable function for 'ANSWER_EXEC' option */
81 static void *answer_exec_enable(void *data)
82 {
83         struct answer_exec_struct *answer_exec = NULL;
84         char *app = ast_strdupa((char*)data), *args = NULL;
85
86         /* Not giving any data to this option is bad, mmmk? */
87         if (ast_strlen_zero(app))
88                 return NULL;
89
90         /* Create new data structure */
91         if (!(answer_exec = ast_calloc(1, sizeof(*answer_exec))))
92                 return NULL;
93         
94         /* Parse out application and arguments */
95         if ((args = strchr(app, '|'))) {
96                 *args++ = '\0';
97                 answer_exec->args = ast_strdup(args);
98         }
99
100         /* Copy application name */
101         ast_copy_string(answer_exec->app, app, sizeof(answer_exec->app));
102
103         return answer_exec;
104 }
105
106 /* Disable function for 'ANSWER_EXEC' option */
107 static int answer_exec_disable(void *data)
108 {
109         struct answer_exec_struct *answer_exec = data;
110
111         /* Make sure we have a value */
112         if (!answer_exec)
113                 return -1;
114
115         /* If arguments are present, free them too */
116         if (answer_exec->args)
117                 free(answer_exec->args);
118
119         /* This is simple - just free the structure */
120         free(answer_exec);
121
122         return 0;
123 }
124
125 /* Application execution function for 'ANSWER_EXEC' option */
126 static void answer_exec_run(struct ast_channel *chan, char *app, char *args)
127 {
128         struct ast_app *ast_app = pbx_findapp(app);
129
130         /* If the application was not found, return immediately */
131         if (!ast_app)
132                 return;
133
134         /* All is well... execute the application */
135         pbx_exec(chan, ast_app, args);
136
137         return;
138 }
139
140 /*! \brief Options structure - maps options to respective handlers (enable/disable). This list MUST be perfectly kept in order, or else madness will happen. */
141 static const struct ast_option_types {
142         enum ast_dial_option option;
143         ast_dial_option_cb_enable enable;
144         ast_dial_option_cb_disable disable;
145 } option_types[] = {
146         { AST_DIAL_OPTION_RINGING, NULL, NULL },                                  /*! Always indicate ringing to caller */
147         { AST_DIAL_OPTION_ANSWER_EXEC, answer_exec_enable, answer_exec_disable }, /*! Execute application upon answer in async mode */
148         { AST_DIAL_OPTION_MAX, NULL, NULL },                                      /*! Terminator of list */
149 };
150
151 /* free the buffer if allocated, and set the pointer to the second arg */
152 #define S_REPLACE(s, new_val)           \
153         do {                            \
154                 if (s)                  \
155                         free(s);        \
156                 s = (new_val);          \
157         } while (0)
158
159 /*! \brief Maximum number of channels we can watch at a time */
160 #define AST_MAX_WATCHERS 256
161
162 /*! \brief Macro for finding the option structure to use on a dialed channel */
163 #define FIND_RELATIVE_OPTION(dial, dial_channel, ast_dial_option) (dial_channel->options[ast_dial_option] ? dial_channel->options[ast_dial_option] : dial->options[ast_dial_option])
164
165 /*! \brief Macro that determines whether a channel is the caller or not */
166 #define IS_CALLER(chan, owner) (chan == owner ? 1 : 0)
167
168 /*! \brief New dialing structure
169  * \note Create a dialing structure
170  * \return Returns a calloc'd ast_dial structure, NULL on failure
171  */
172 struct ast_dial *ast_dial_create(void)
173 {
174         struct ast_dial *dial = NULL;
175
176         /* Allocate new memory for structure */
177         if (!(dial = ast_calloc(1, sizeof(*dial))))
178                 return NULL;
179
180         /* Initialize list of channels */
181         AST_LIST_HEAD_INIT_NOLOCK(&dial->channels);
182
183         /* Initialize thread to NULL */
184         dial->thread = AST_PTHREADT_NULL;
185
186         return dial;
187 }
188
189 /*! \brief Append a channel
190  * \note Appends a channel to a dialing structure
191  * \return Returns channel reference number on success, -1 on failure
192  */
193 int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device)
194 {
195         struct ast_dial_channel *channel = NULL;
196
197         /* Make sure we have required arguments */
198         if (!dial || !tech || !device)
199                 return -1;
200
201         /* Allocate new memory for dialed channel structure */
202         if (!(channel = ast_calloc(1, sizeof(*channel))))
203                 return -1;
204
205         /* Record technology and device for when we actually dial */
206         channel->tech = tech;
207         channel->device = device;
208
209         /* Grab reference number from dial structure */
210         channel->num = ast_atomic_fetchadd_int(&dial->num, +1);
211
212         /* Insert into channels list */
213         AST_LIST_INSERT_TAIL(&dial->channels, channel, list);
214
215         return channel->num;
216 }
217
218 /*! \brief Helper function that does the beginning dialing */
219 static int begin_dial(struct ast_dial *dial, struct ast_channel *chan)
220 {
221         struct ast_dial_channel *channel = NULL;
222         int success = 0, res = 0;
223
224         /* Iterate through channel list, requesting and calling each one */
225         AST_LIST_TRAVERSE(&dial->channels, channel, list) {
226                 char numsubst[AST_MAX_EXTENSION];
227
228                 /* Copy device string over */
229                 ast_copy_string(numsubst, channel->device, sizeof(numsubst));
230
231                 /* Request that the channel be created */
232                 if (!(channel->owner = ast_request(channel->tech, 
233                         chan ? chan->nativeformats : AST_FORMAT_AUDIO_MASK, numsubst, &channel->cause))) {
234                         continue;
235                 }
236
237                 channel->owner->appl = "AppDial2";
238                 channel->owner->data = "(Outgoing Line)";
239                 channel->owner->whentohangup = 0;
240
241                 /* Inherit everything from he who spawned this Dial */
242                 if (chan) {
243                         ast_channel_inherit_variables(chan, channel->owner);
244
245                         /* Copy over callerid information */
246                         S_REPLACE(channel->owner->cid.cid_num, ast_strdup(chan->cid.cid_num));
247                         S_REPLACE(channel->owner->cid.cid_name, ast_strdup(chan->cid.cid_name));
248                         S_REPLACE(channel->owner->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
249                         S_REPLACE(channel->owner->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
250         
251                         ast_string_field_set(channel->owner, language, chan->language);
252                         ast_string_field_set(channel->owner, accountcode, chan->accountcode);
253                         channel->owner->cdrflags = chan->cdrflags;
254                         if (ast_strlen_zero(channel->owner->musicclass))
255                                 ast_string_field_set(channel->owner, musicclass, chan->musicclass);
256         
257                         channel->owner->cid.cid_pres = chan->cid.cid_pres;
258                         channel->owner->cid.cid_ton = chan->cid.cid_ton;
259                         channel->owner->cid.cid_tns = chan->cid.cid_tns;
260                         channel->owner->adsicpe = chan->adsicpe;
261                         channel->owner->transfercapability = chan->transfercapability;
262                 }
263
264                 /* Actually call the device */
265                 if ((res = ast_call(channel->owner, numsubst, 0))) {
266                         ast_hangup(channel->owner);
267                         channel->owner = NULL;
268                 } else {
269                         success++;
270                         if (option_verbose > 2)
271                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
272                 }
273         }
274
275         /* If number of failures matches the number of channels, then this truly failed */
276         return success;
277 }
278
279 /*! \brief Helper function that finds the dialed channel based on owner */
280 static struct ast_dial_channel *find_relative_dial_channel(struct ast_dial *dial, struct ast_channel *owner)
281 {
282         struct ast_dial_channel *channel = NULL;
283
284         AST_LIST_TRAVERSE(&dial->channels, channel, list) {
285                 if (channel->owner == owner)
286                         break;
287         }
288
289         return channel;
290 }
291
292 static void set_state(struct ast_dial *dial, enum ast_dial_result state)
293 {
294         dial->state = state;
295
296         if (dial->state_callback)
297                 dial->state_callback(dial);
298 }
299
300 /*! \brief Helper function that handles control frames WITH owner */
301 static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr, struct ast_channel *chan)
302 {
303         if (fr->frametype == AST_FRAME_CONTROL) {
304                 switch (fr->subclass) {
305                 case AST_CONTROL_ANSWER:
306                         if (option_verbose > 2)
307                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", channel->owner->name, chan->name);
308                         AST_LIST_REMOVE(&dial->channels, channel, list);
309                         AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
310                         set_state(dial, AST_DIAL_RESULT_ANSWERED);
311                         break;
312                 case AST_CONTROL_BUSY:
313                         if (option_verbose > 2)
314                                 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", channel->owner->name);
315                         ast_hangup(channel->owner);
316                         channel->owner = NULL;
317                         break;
318                 case AST_CONTROL_CONGESTION:
319                         if (option_verbose > 2)
320                                 ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", channel->owner->name);
321                         ast_hangup(channel->owner);
322                         channel->owner = NULL;
323                         break;
324                 case AST_CONTROL_RINGING:
325                         if (option_verbose > 2)
326                                 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", channel->owner->name);
327                         ast_indicate(chan, AST_CONTROL_RINGING);
328                         break;
329                 case AST_CONTROL_PROGRESS:
330                         if (option_verbose > 2)
331                                 ast_verbose (VERBOSE_PREFIX_3 "%s is making progress, passing it to %s\n", channel->owner->name, chan->name);
332                         ast_indicate(chan, AST_CONTROL_PROGRESS);
333                         break;
334                 case AST_CONTROL_VIDUPDATE:
335                         if (option_verbose > 2)
336                                 ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", channel->owner->name, chan->name);
337                         ast_indicate(chan, AST_CONTROL_VIDUPDATE);
338                         break;
339                 case AST_CONTROL_PROCEEDING:
340                         if (option_verbose > 2)
341                                 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name);
342                         ast_indicate(chan, AST_CONTROL_PROCEEDING);
343                         break;
344                 case AST_CONTROL_HOLD:
345                         if (option_verbose > 2)
346                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", chan->name);
347                         ast_indicate(chan, AST_CONTROL_HOLD);
348                         break;
349                 case AST_CONTROL_UNHOLD:
350                         if (option_verbose > 2)
351                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", chan->name);
352                         ast_indicate(chan, AST_CONTROL_UNHOLD);
353                         break;
354                 case AST_CONTROL_OFFHOOK:
355                 case AST_CONTROL_FLASH:
356                         break;
357                 case -1:
358                         /* Prod the channel */
359                         ast_indicate(chan, -1);
360                         break;
361                 default:
362                         break;
363                 }
364         }
365
366         return;
367 }
368
369 /*! \brief Helper function that handles control frames WITHOUT owner */
370 static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr)
371 {
372         /* If we have no owner we can only update the state of the dial structure, so only look at control frames */
373         if (fr->frametype != AST_FRAME_CONTROL)
374                 return;
375
376         switch (fr->subclass) {
377         case AST_CONTROL_ANSWER:
378                 if (option_verbose > 2)
379                         ast_verbose( VERBOSE_PREFIX_3 "%s answered\n", channel->owner->name);
380                 AST_LIST_REMOVE(&dial->channels, channel, list);
381                 AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
382                 set_state(dial, AST_DIAL_RESULT_ANSWERED);
383                 break;
384         case AST_CONTROL_BUSY:
385                 if (option_verbose > 2)
386                         ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", channel->owner->name);
387                 ast_hangup(channel->owner);
388                 channel->owner = NULL;
389                 break;
390         case AST_CONTROL_CONGESTION:
391                 if (option_verbose > 2)
392                         ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", channel->owner->name);
393                 ast_hangup(channel->owner);
394                 channel->owner = NULL;
395                 break;
396         case AST_CONTROL_RINGING:
397                 if (option_verbose > 2)
398                         ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", channel->owner->name);
399                 set_state(dial, AST_DIAL_RESULT_RINGING);
400                 break;
401         case AST_CONTROL_PROGRESS:
402                 if (option_verbose > 2)
403                         ast_verbose (VERBOSE_PREFIX_3 "%s is making progress\n", channel->owner->name);
404                 set_state(dial, AST_DIAL_RESULT_PROGRESS);
405                 break;
406         case AST_CONTROL_PROCEEDING:
407                 if (option_verbose > 2)
408                         ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding\n", channel->owner->name);
409                 set_state(dial, AST_DIAL_RESULT_PROCEEDING);
410                 break;
411         default:
412                 break;
413         }
414
415         return;
416 }
417
418 /*! \brief Helper function that basically keeps tabs on dialing attempts */
419 static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_channel *chan)
420 {
421         int timeout = -1, count = 0;
422         struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL;
423         struct ast_dial_channel *channel = NULL;
424         struct answer_exec_struct *answer_exec = NULL;
425
426         set_state(dial, AST_DIAL_RESULT_TRYING);
427
428         /* If the "always indicate ringing" option is set, change state to ringing and indicate to the owner if present */
429         if (dial->options[AST_DIAL_OPTION_RINGING]) {
430                 set_state(dial, AST_DIAL_RESULT_RINGING);
431                 if (chan)
432                         ast_indicate(chan, AST_CONTROL_RINGING);
433         }
434
435         /* Go into an infinite loop while we are trying */
436         while ((dial->state != AST_DIAL_RESULT_UNANSWERED) && (dial->state != AST_DIAL_RESULT_ANSWERED) && (dial->state != AST_DIAL_RESULT_HANGUP) && (dial->state != AST_DIAL_RESULT_TIMEOUT)) {
437                 int pos = 0;
438                 struct ast_frame *fr = NULL;
439
440                 /* Set up channel structure array */
441                 pos = count = 0;
442                 if (chan)
443                         cs[pos++] = chan;
444
445                 /* Add channels we are attempting to dial */
446                 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
447                         if (channel->owner) {
448                                 cs[pos++] = channel->owner;
449                                 count++;
450                         }
451                 }
452
453                 /* If we have no outbound channels in progress, switch state to unanswered and stop */
454                 if (!count) {
455                         set_state(dial, AST_DIAL_RESULT_UNANSWERED);
456                         break;
457                 }
458
459                 /* Just to be safe... */
460                 if (dial->thread == AST_PTHREADT_STOP)
461                         break;
462
463                 /* Wait for frames from channels */
464                 who = ast_waitfor_n(cs, pos, &timeout);
465
466                 /* Check to see if our thread is being cancelled */
467                 if (dial->thread == AST_PTHREADT_STOP)
468                         break;
469
470                 /* If we are not being cancelled and we have no channel, then timeout was tripped */
471                 if (!who)
472                         continue;
473
474                 /* Find relative dial channel */
475                 if (!chan || !IS_CALLER(chan, who))
476                         channel = find_relative_dial_channel(dial, who);
477
478                 /* Attempt to read in a frame */
479                 if (!(fr = ast_read(who))) {
480                         /* If this is the caller then we switch state to hangup and stop */
481                         if (chan && IS_CALLER(chan, who)) {
482                                 set_state(dial, AST_DIAL_RESULT_HANGUP);
483                                 break;
484                         }
485                         ast_hangup(who);
486                         channel->owner = NULL;
487                         continue;
488                 }
489
490                 /* Process the frame */
491                 if (chan)
492                         handle_frame(dial, channel, fr, chan);
493                 else
494                         handle_frame_ownerless(dial, channel, fr);
495
496                 /* Free the received frame and start all over */
497                 ast_frfree(fr);
498         }
499
500         /* Do post-processing from loop */
501         if (dial->state == AST_DIAL_RESULT_ANSWERED) {
502                 /* Hangup everything except that which answered */
503                 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
504                         if (!channel->owner || channel->owner == who)
505                                 continue;
506                         ast_hangup(channel->owner);
507                         channel->owner = NULL;
508                 }
509                 /* If ANSWER_EXEC is enabled as an option, execute application on answered channel */
510                 if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC)))
511                         answer_exec_run(who, answer_exec->app, answer_exec->args);
512         } else if (dial->state == AST_DIAL_RESULT_HANGUP) {
513                 /* Hangup everything */
514                 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
515                         if (!channel->owner)
516                                 continue;
517                         ast_hangup(channel->owner);
518                         channel->owner = NULL;
519                 }
520         }
521
522         return dial->state;
523 }
524
525 /*! \brief Dial async thread function */
526 static void *async_dial(void *data)
527 {
528         struct ast_dial *dial = data;
529
530         /* This is really really simple... we basically pass monitor_dial a NULL owner and it changes it's behavior */
531         monitor_dial(dial, NULL);
532
533         return NULL;
534 }
535
536 /*! \brief Execute dialing synchronously or asynchronously
537  * \note Dials channels in a dial structure.
538  * \return Returns dial result code. (TRYING/INVALID/FAILED/ANSWERED/TIMEOUT/UNANSWERED).
539  */
540 enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
541 {
542         enum ast_dial_result res = AST_DIAL_RESULT_TRYING;
543
544         /* Ensure required arguments are passed */
545         if (!dial || (!chan && !async)) {
546                 ast_log(LOG_DEBUG, "invalid #1\n");
547                 return AST_DIAL_RESULT_INVALID;
548         }
549
550         /* If there are no channels to dial we can't very well try to dial them */
551         if (AST_LIST_EMPTY(&dial->channels)) {
552                 ast_log(LOG_DEBUG, "invalid #2\n");
553                 return AST_DIAL_RESULT_INVALID;
554         }
555
556         /* Dial each requested channel */
557         if (!begin_dial(dial, chan))
558                 return AST_DIAL_RESULT_FAILED;
559
560         /* If we are running async spawn a thread and send it away... otherwise block here */
561         if (async) {
562                 dial->state = AST_DIAL_RESULT_TRYING;
563                 /* Try to create a thread */
564                 if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
565                         /* Failed to create the thread - hangup all dialed channels and return failed */
566                         ast_dial_hangup(dial);
567                         res = AST_DIAL_RESULT_FAILED;
568                 }
569         } else {
570                 res = monitor_dial(dial, chan);
571         }
572
573         return res;
574 }
575
576 /*! \brief Return channel that answered
577  * \note Returns the Asterisk channel that answered
578  * \param dial Dialing structure
579  */
580 struct ast_channel *ast_dial_answered(struct ast_dial *dial)
581 {
582         if (!dial)
583                 return NULL;
584
585         return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL);
586 }
587
588 /*! \brief Return state of dial
589  * \note Returns the state of the dial attempt
590  * \param dial Dialing structure
591  */
592 enum ast_dial_result ast_dial_state(struct ast_dial *dial)
593 {
594         return dial->state;
595 }
596
597 /*! \brief Cancel async thread
598  * \note Cancel a running async thread
599  * \param dial Dialing structure
600  */
601 enum ast_dial_result ast_dial_join(struct ast_dial *dial)
602 {
603         pthread_t thread;
604
605         /* If the dial structure is not running in async, return failed */
606         if (dial->thread == AST_PTHREADT_NULL)
607                 return AST_DIAL_RESULT_FAILED;
608
609         /* Record thread */
610         thread = dial->thread;
611
612         /* Stop the thread */
613         dial->thread = AST_PTHREADT_STOP;
614
615         /* Now we signal it with SIGURG so it will break out of it's waitfor */
616         pthread_kill(thread, SIGURG);
617
618         /* Finally wait for the thread to exit */
619         pthread_join(thread, NULL);
620
621         /* Yay thread is all gone */
622         dial->thread = AST_PTHREADT_NULL;
623
624         return dial->state;
625 }
626
627 /*! \brief Hangup channels
628  * \note Hangup all active channels
629  * \param dial Dialing structure
630  */
631 void ast_dial_hangup(struct ast_dial *dial)
632 {
633         struct ast_dial_channel *channel = NULL;
634
635         if (!dial)
636                 return;
637         
638         AST_LIST_TRAVERSE(&dial->channels, channel, list) {
639                 if (channel->owner) {
640                         ast_hangup(channel->owner);
641                         channel->owner = NULL;
642                 }
643         }
644
645         return;
646 }
647
648 /*! \brief Destroys a dialing structure
649  * \note Destroys (free's) the given ast_dial structure
650  * \param dial Dialing structure to free
651  * \return Returns 0 on success, -1 on failure
652  */
653 int ast_dial_destroy(struct ast_dial *dial)
654 {
655         int i = 0;
656         struct ast_dial_channel *channel = NULL;
657
658         if (!dial)
659                 return -1;
660         
661         /* Hangup and deallocate all the dialed channels */
662         AST_LIST_TRAVERSE(&dial->channels, channel, list) {
663                 /* Disable any enabled options */
664                 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
665                         if (!channel->options[i])
666                                 continue;
667                         if (option_types[i].disable)
668                                 option_types[i].disable(channel->options[i]);
669                         channel->options[i] = NULL;
670                 }
671                 /* Hang up channel if need be */
672                 if (channel->owner) {
673                         ast_hangup(channel->owner);
674                         channel->owner = NULL;
675                 }
676                 /* Free structure */
677                 free(channel);
678         }
679        
680         /* Disable any enabled options globally */
681         for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
682                 if (!dial->options[i])
683                         continue;
684                 if (option_types[i].disable)
685                         option_types[i].disable(dial->options[i]);
686                 dial->options[i] = NULL;
687         }
688
689         /* Free structure */
690         free(dial);
691
692         return 0;
693 }
694
695 /*! \brief Enables an option globally
696  * \param dial Dial structure to enable option on
697  * \param option Option to enable
698  * \param data Data to pass to this option (not always needed)
699  * \return Returns 0 on success, -1 on failure
700  */
701 int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
702 {
703         /* If the option is already enabled, return failure */
704         if (dial->options[option])
705                 return -1;
706
707         /* Execute enable callback if it exists, if not simply make sure the value is set */
708         if (option_types[option].enable)
709                 dial->options[option] = option_types[option].enable(data);
710         else
711                 dial->options[option] = (void*)1;
712
713         return 0;
714 }
715
716 /*! \brief Enables an option per channel
717  * \param dial Dial structure
718  * \param num Channel number to enable option on
719  * \param option Option to enable
720  * \param data Data to pass to this option (not always needed)
721  * \return Returns 0 on success, -1 on failure
722  */
723 int ast_dial_option_enable(struct ast_dial *dial, int num, enum ast_dial_option option, void *data)
724 {
725         struct ast_dial_channel *channel = NULL;
726
727         /* Ensure we have required arguments */
728         if (!dial || AST_LIST_EMPTY(&dial->channels))
729                 return -1;
730         
731         /* Look for channel, we can sort of cheat and predict things - the last channel in the list will probably be what they want */
732         if (AST_LIST_LAST(&dial->channels)->num != num) {
733                 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
734                         if (channel->num == num)
735                                 break;
736                 }
737         } else {
738                 channel = AST_LIST_LAST(&dial->channels);
739         }
740
741         /* If none found, return failure */
742         if (!channel)
743                 return -1;
744
745         /* If the option is already enabled, return failure */
746         if (channel->options[option])
747                 return -1;
748
749         /* Execute enable callback if it exists, if not simply make sure the value is set */
750         if (option_types[option].enable)
751                 channel->options[option] = option_types[option].enable(data);
752         else
753                 channel->options[option] = (void*)1;
754
755         return 0;
756 }
757
758 /*! \brief Disables an option globally
759  * \param dial Dial structure to disable option on
760  * \param option Option to disable
761  * \return Returns 0 on success, -1 on failure
762  */
763 int ast_dial_option_global_disable(struct ast_dial *dial, enum ast_dial_option option)
764 {
765         /* If the option is not enabled, return failure */
766         if (!dial->options[option])
767                 return -1;
768
769         /* Execute callback of option to disable if it exists */
770         if (option_types[option].disable)
771                 option_types[option].disable(dial->options[option]);
772
773         /* Finally disable option on the structure */
774         dial->options[option] = NULL;
775
776         return 0;
777 }
778
779 /*! \brief Disables an option per channel
780  * \param dial Dial structure
781  * \param num Channel number to disable option on
782  * \param option Option to disable
783  * \return Returns 0 on success, -1 on failure
784  */
785 int ast_dial_option_disable(struct ast_dial *dial, int num, enum ast_dial_option option)
786 {
787         struct ast_dial_channel *channel = NULL;
788
789         /* Ensure we have required arguments */
790         if (!dial || AST_LIST_EMPTY(&dial->channels))
791                 return -1;
792
793         /* Look for channel, we can sort of cheat and predict things - the last channel in the list will probably be what they want */
794         if (AST_LIST_LAST(&dial->channels)->num != num) {
795                 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
796                         if (channel->num == num)
797                                 break;
798                 }
799         } else {
800                 channel = AST_LIST_LAST(&dial->channels);
801         }
802
803         /* If none found, return failure */
804         if (!channel)
805                 return -1;
806
807         /* If the option is not enabled, return failure */
808         if (!channel->options[option])
809                 return -1;
810
811         /* Execute callback of option to disable it if it exists */
812         if (option_types[option].disable)
813                 option_types[option].disable(channel->options[option]);
814
815         /* Finally disable the option on the structure */
816         channel->options[option] = NULL;
817
818         return 0;
819 }
820
821 void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
822 {
823         dial->state_callback = callback;
824 }