00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 276347 $")
00029
00030 #include <sys/time.h>
00031 #include <signal.h>
00032
00033 #include "asterisk/channel.h"
00034 #include "asterisk/utils.h"
00035 #include "asterisk/lock.h"
00036 #include "asterisk/linkedlists.h"
00037 #include "asterisk/dial.h"
00038 #include "asterisk/pbx.h"
00039 #include "asterisk/musiconhold.h"
00040 #include "asterisk/app.h"
00041
00042
00043 struct ast_dial {
00044 int num;
00045 int timeout;
00046 int actual_timeout;
00047 enum ast_dial_result state;
00048 void *options[AST_DIAL_OPTION_MAX];
00049 ast_dial_state_callback state_callback;
00050 AST_LIST_HEAD(, ast_dial_channel) channels;
00051 pthread_t thread;
00052 ast_mutex_t lock;
00053 };
00054
00055
00056 struct ast_dial_channel {
00057 int num;
00058 int timeout;
00059 char *tech;
00060 char *device;
00061 void *options[AST_DIAL_OPTION_MAX];
00062 int cause;
00063 unsigned int is_running_app:1;
00064 struct ast_channel *owner;
00065 AST_LIST_ENTRY(ast_dial_channel) list;
00066 };
00067
00068
00069 typedef void *(*ast_dial_option_cb_enable)(void *data);
00070
00071
00072 typedef int (*ast_dial_option_cb_disable)(void *data);
00073
00074
00075 struct answer_exec_struct {
00076 char app[AST_MAX_APP];
00077 char *args;
00078 };
00079
00080
00081 static void *answer_exec_enable(void *data)
00082 {
00083 struct answer_exec_struct *answer_exec = NULL;
00084 char *app = ast_strdupa((char*)data), *args = NULL;
00085
00086
00087 if (ast_strlen_zero(app))
00088 return NULL;
00089
00090
00091 if (!(answer_exec = ast_calloc(1, sizeof(*answer_exec))))
00092 return NULL;
00093
00094
00095 if ((args = strchr(app, ','))) {
00096 *args++ = '\0';
00097 answer_exec->args = ast_strdup(args);
00098 }
00099
00100
00101 ast_copy_string(answer_exec->app, app, sizeof(answer_exec->app));
00102
00103 return answer_exec;
00104 }
00105
00106
00107 static int answer_exec_disable(void *data)
00108 {
00109 struct answer_exec_struct *answer_exec = data;
00110
00111
00112 if (!answer_exec)
00113 return -1;
00114
00115
00116 if (answer_exec->args)
00117 ast_free(answer_exec->args);
00118
00119
00120 ast_free(answer_exec);
00121
00122 return 0;
00123 }
00124
00125 static void *music_enable(void *data)
00126 {
00127 return ast_strdup(data);
00128 }
00129
00130 static int music_disable(void *data)
00131 {
00132 if (!data)
00133 return -1;
00134
00135 ast_free(data);
00136
00137 return 0;
00138 }
00139
00140
00141 static void answer_exec_run(struct ast_dial *dial, struct ast_dial_channel *dial_channel, char *app, char *args)
00142 {
00143 struct ast_channel *chan = dial_channel->owner;
00144 struct ast_app *ast_app = pbx_findapp(app);
00145
00146
00147 if (!ast_app)
00148 return;
00149
00150
00151 pbx_exec(chan, ast_app, args);
00152
00153
00154 ast_mutex_lock(&dial->lock);
00155 if (dial->thread != AST_PTHREADT_STOP) {
00156 ast_hangup(chan);
00157 dial_channel->owner = NULL;
00158 }
00159 ast_mutex_unlock(&dial->lock);
00160
00161 return;
00162 }
00163
00164
00165 static const struct ast_option_types {
00166 enum ast_dial_option option;
00167 ast_dial_option_cb_enable enable;
00168 ast_dial_option_cb_disable disable;
00169 } option_types[] = {
00170 { AST_DIAL_OPTION_RINGING, NULL, NULL },
00171 { AST_DIAL_OPTION_ANSWER_EXEC, answer_exec_enable, answer_exec_disable },
00172 { AST_DIAL_OPTION_MUSIC, music_enable, music_disable },
00173 { AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, NULL, NULL },
00174 { AST_DIAL_OPTION_MAX, NULL, NULL },
00175 };
00176
00177
00178 #define AST_MAX_WATCHERS 256
00179
00180
00181 #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])
00182
00183
00184 #define IS_CALLER(chan, owner) (chan == owner ? 1 : 0)
00185
00186
00187
00188
00189
00190 struct ast_dial *ast_dial_create(void)
00191 {
00192 struct ast_dial *dial = NULL;
00193
00194
00195 if (!(dial = ast_calloc(1, sizeof(*dial))))
00196 return NULL;
00197
00198
00199 AST_LIST_HEAD_INIT(&dial->channels);
00200
00201
00202 dial->thread = AST_PTHREADT_NULL;
00203
00204
00205 dial->timeout = -1;
00206 dial->actual_timeout = -1;
00207
00208
00209 ast_mutex_init(&dial->lock);
00210
00211 return dial;
00212 }
00213
00214
00215
00216
00217
00218 int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device)
00219 {
00220 struct ast_dial_channel *channel = NULL;
00221
00222
00223 if (!dial || !tech || !device)
00224 return -1;
00225
00226
00227 if (!(channel = ast_calloc(1, sizeof(*channel))))
00228 return -1;
00229
00230
00231 channel->tech = ast_strdup(tech);
00232 channel->device = ast_strdup(device);
00233
00234
00235 channel->num = ast_atomic_fetchadd_int(&dial->num, +1);
00236
00237
00238 channel->timeout = -1;
00239
00240
00241 AST_LIST_INSERT_TAIL(&dial->channels, channel, list);
00242
00243 return channel->num;
00244 }
00245
00246
00247 static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_channel *chan)
00248 {
00249 char numsubst[AST_MAX_EXTENSION];
00250 int res = 1;
00251
00252
00253 ast_copy_string(numsubst, channel->device, sizeof(numsubst));
00254
00255
00256 if (!(channel->owner = ast_request(channel->tech, chan ? chan->nativeformats : AST_FORMAT_AUDIO_MASK, chan, numsubst, &channel->cause)))
00257 return -1;
00258
00259 channel->owner->appl = "AppDial2";
00260 channel->owner->data = "(Outgoing Line)";
00261 memset(&channel->owner->whentohangup, 0, sizeof(channel->owner->whentohangup));
00262
00263
00264 if (chan) {
00265 ast_channel_inherit_variables(chan, channel->owner);
00266 ast_channel_datastore_inherit(chan, channel->owner);
00267
00268
00269 ast_party_redirecting_copy(&channel->owner->redirecting, &chan->redirecting);
00270
00271 channel->owner->dialed.transit_network_select = chan->dialed.transit_network_select;
00272
00273 ast_connected_line_copy_from_caller(&channel->owner->connected, &chan->caller);
00274
00275 ast_string_field_set(channel->owner, language, chan->language);
00276 ast_string_field_set(channel->owner, accountcode, chan->accountcode);
00277 if (ast_strlen_zero(channel->owner->musicclass))
00278 ast_string_field_set(channel->owner, musicclass, chan->musicclass);
00279
00280 channel->owner->adsicpe = chan->adsicpe;
00281 channel->owner->transfercapability = chan->transfercapability;
00282 }
00283
00284
00285 if ((res = ast_call(channel->owner, numsubst, 0))) {
00286 res = 0;
00287 ast_hangup(channel->owner);
00288 channel->owner = NULL;
00289 } else {
00290 if (chan)
00291 ast_poll_channel_add(chan, channel->owner);
00292 res = 1;
00293 ast_verb(3, "Called %s\n", numsubst);
00294 }
00295
00296 return res;
00297 }
00298
00299
00300 static int begin_dial(struct ast_dial *dial, struct ast_channel *chan)
00301 {
00302 struct ast_dial_channel *channel = NULL;
00303 int success = 0;
00304
00305
00306 AST_LIST_LOCK(&dial->channels);
00307 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00308 success += begin_dial_channel(channel, chan);
00309 }
00310 AST_LIST_UNLOCK(&dial->channels);
00311
00312
00313 return success;
00314 }
00315
00316
00317 static int handle_call_forward(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_channel *chan)
00318 {
00319 struct ast_channel *original = channel->owner;
00320 char *tmp = ast_strdupa(channel->owner->call_forward);
00321 char *tech = "Local", *device = tmp, *stuff;
00322
00323
00324 if (FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING)) {
00325 ast_hangup(original);
00326 channel->owner = NULL;
00327 return 0;
00328 }
00329
00330
00331 if ((stuff = strchr(tmp, '/'))) {
00332 *stuff++ = '\0';
00333 tech = tmp;
00334 device = stuff;
00335 }
00336
00337
00338 ast_free(channel->tech);
00339 ast_free(channel->device);
00340
00341
00342 channel->tech = ast_strdup(tech);
00343 channel->device = ast_strdup(device);
00344 AST_LIST_UNLOCK(&dial->channels);
00345
00346
00347 begin_dial_channel(channel, chan);
00348
00349
00350 ast_hangup(original);
00351
00352 return 0;
00353 }
00354
00355
00356 static struct ast_dial_channel *find_relative_dial_channel(struct ast_dial *dial, struct ast_channel *owner)
00357 {
00358 struct ast_dial_channel *channel = NULL;
00359
00360 AST_LIST_LOCK(&dial->channels);
00361 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00362 if (channel->owner == owner)
00363 break;
00364 }
00365 AST_LIST_UNLOCK(&dial->channels);
00366
00367 return channel;
00368 }
00369
00370 static void set_state(struct ast_dial *dial, enum ast_dial_result state)
00371 {
00372 dial->state = state;
00373
00374 if (dial->state_callback)
00375 dial->state_callback(dial);
00376 }
00377
00378
00379 static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr, struct ast_channel *chan)
00380 {
00381 if (fr->frametype == AST_FRAME_CONTROL) {
00382 switch (fr->subclass.integer) {
00383 case AST_CONTROL_ANSWER:
00384 ast_verb(3, "%s answered %s\n", channel->owner->name, chan->name);
00385 AST_LIST_LOCK(&dial->channels);
00386 AST_LIST_REMOVE(&dial->channels, channel, list);
00387 AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
00388 AST_LIST_UNLOCK(&dial->channels);
00389 set_state(dial, AST_DIAL_RESULT_ANSWERED);
00390 break;
00391 case AST_CONTROL_BUSY:
00392 ast_verb(3, "%s is busy\n", channel->owner->name);
00393 ast_hangup(channel->owner);
00394 channel->owner = NULL;
00395 break;
00396 case AST_CONTROL_CONGESTION:
00397 ast_verb(3, "%s is circuit-busy\n", channel->owner->name);
00398 ast_hangup(channel->owner);
00399 channel->owner = NULL;
00400 break;
00401 case AST_CONTROL_RINGING:
00402 ast_verb(3, "%s is ringing\n", channel->owner->name);
00403 if (!dial->options[AST_DIAL_OPTION_MUSIC])
00404 ast_indicate(chan, AST_CONTROL_RINGING);
00405 set_state(dial, AST_DIAL_RESULT_RINGING);
00406 break;
00407 case AST_CONTROL_PROGRESS:
00408 ast_verb(3, "%s is making progress, passing it to %s\n", channel->owner->name, chan->name);
00409 ast_indicate(chan, AST_CONTROL_PROGRESS);
00410 set_state(dial, AST_DIAL_RESULT_PROGRESS);
00411 break;
00412 case AST_CONTROL_VIDUPDATE:
00413 ast_verb(3, "%s requested a video update, passing it to %s\n", channel->owner->name, chan->name);
00414 ast_indicate(chan, AST_CONTROL_VIDUPDATE);
00415 break;
00416 case AST_CONTROL_SRCUPDATE:
00417 if (option_verbose > 2)
00418 ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name);
00419 ast_indicate(chan, AST_CONTROL_SRCUPDATE);
00420 break;
00421 case AST_CONTROL_CONNECTED_LINE:
00422 ast_verb(3, "%s connected line has changed, passing it to %s\n", channel->owner->name, chan->name);
00423 if (ast_channel_connected_line_macro(channel->owner, chan, fr, 1, 1)) {
00424 ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
00425 }
00426 break;
00427 case AST_CONTROL_REDIRECTING:
00428 ast_verb(3, "%s redirecting info has changed, passing it to %s\n", channel->owner->name, chan->name);
00429 if (ast_channel_redirecting_macro(channel->owner, chan, fr, 1, 1)) {
00430 ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen);
00431 }
00432 break;
00433 case AST_CONTROL_PROCEEDING:
00434 ast_verb(3, "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name);
00435 ast_indicate(chan, AST_CONTROL_PROCEEDING);
00436 set_state(dial, AST_DIAL_RESULT_PROCEEDING);
00437 break;
00438 case AST_CONTROL_HOLD:
00439 ast_verb(3, "Call on %s placed on hold\n", chan->name);
00440 ast_indicate(chan, AST_CONTROL_HOLD);
00441 break;
00442 case AST_CONTROL_UNHOLD:
00443 ast_verb(3, "Call on %s left from hold\n", chan->name);
00444 ast_indicate(chan, AST_CONTROL_UNHOLD);
00445 break;
00446 case AST_CONTROL_OFFHOOK:
00447 case AST_CONTROL_FLASH:
00448 break;
00449 case -1:
00450
00451 ast_indicate(chan, -1);
00452 break;
00453 default:
00454 break;
00455 }
00456 }
00457
00458 return;
00459 }
00460
00461
00462 static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr)
00463 {
00464
00465 if (fr->frametype != AST_FRAME_CONTROL)
00466 return;
00467
00468 switch (fr->subclass.integer) {
00469 case AST_CONTROL_ANSWER:
00470 ast_verb(3, "%s answered\n", channel->owner->name);
00471 AST_LIST_LOCK(&dial->channels);
00472 AST_LIST_REMOVE(&dial->channels, channel, list);
00473 AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
00474 AST_LIST_UNLOCK(&dial->channels);
00475 set_state(dial, AST_DIAL_RESULT_ANSWERED);
00476 break;
00477 case AST_CONTROL_BUSY:
00478 ast_verb(3, "%s is busy\n", channel->owner->name);
00479 ast_hangup(channel->owner);
00480 channel->owner = NULL;
00481 break;
00482 case AST_CONTROL_CONGESTION:
00483 ast_verb(3, "%s is circuit-busy\n", channel->owner->name);
00484 ast_hangup(channel->owner);
00485 channel->owner = NULL;
00486 break;
00487 case AST_CONTROL_RINGING:
00488 ast_verb(3, "%s is ringing\n", channel->owner->name);
00489 set_state(dial, AST_DIAL_RESULT_RINGING);
00490 break;
00491 case AST_CONTROL_PROGRESS:
00492 ast_verb(3, "%s is making progress\n", channel->owner->name);
00493 set_state(dial, AST_DIAL_RESULT_PROGRESS);
00494 break;
00495 case AST_CONTROL_PROCEEDING:
00496 ast_verb(3, "%s is proceeding\n", channel->owner->name);
00497 set_state(dial, AST_DIAL_RESULT_PROCEEDING);
00498 break;
00499 default:
00500 break;
00501 }
00502
00503 return;
00504 }
00505
00506
00507 static int handle_timeout_trip(struct ast_dial *dial, struct timeval start)
00508 {
00509 struct ast_dial_channel *channel = NULL;
00510 int diff = ast_tvdiff_ms(ast_tvnow(), start), lowest_timeout = -1, new_timeout = -1;
00511
00512
00513 if (diff >= dial->timeout) {
00514 set_state(dial, AST_DIAL_RESULT_TIMEOUT);
00515 new_timeout = 0;
00516 }
00517
00518
00519 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00520 if (dial->state == AST_DIAL_RESULT_TIMEOUT || diff >= channel->timeout) {
00521 ast_hangup(channel->owner);
00522 channel->owner = NULL;
00523 } else if ((lowest_timeout == -1) || (lowest_timeout > channel->timeout)) {
00524 lowest_timeout = channel->timeout;
00525 }
00526 }
00527
00528
00529 if (lowest_timeout >= 0)
00530 new_timeout = lowest_timeout - diff;
00531
00532 return new_timeout;
00533 }
00534
00535
00536 static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_channel *chan)
00537 {
00538 int timeout = -1;
00539 struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL;
00540 struct ast_dial_channel *channel = NULL;
00541 struct answer_exec_struct *answer_exec = NULL;
00542 struct timeval start;
00543
00544 set_state(dial, AST_DIAL_RESULT_TRYING);
00545
00546
00547 if (dial->options[AST_DIAL_OPTION_RINGING]) {
00548 set_state(dial, AST_DIAL_RESULT_RINGING);
00549 if (chan)
00550 ast_indicate(chan, AST_CONTROL_RINGING);
00551 } else if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
00552 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) {
00553 char *original_moh = ast_strdupa(chan->musicclass);
00554 ast_indicate(chan, -1);
00555 ast_string_field_set(chan, musicclass, dial->options[AST_DIAL_OPTION_MUSIC]);
00556 ast_moh_start(chan, dial->options[AST_DIAL_OPTION_MUSIC], NULL);
00557 ast_string_field_set(chan, musicclass, original_moh);
00558 }
00559
00560
00561 start = ast_tvnow();
00562
00563
00564 timeout = dial->actual_timeout;
00565
00566
00567 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)) {
00568 int pos = 0, count = 0;
00569 struct ast_frame *fr = NULL;
00570
00571
00572 pos = count = 0;
00573 if (chan)
00574 cs[pos++] = chan;
00575
00576
00577 AST_LIST_LOCK(&dial->channels);
00578 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00579 if (channel->owner) {
00580 cs[pos++] = channel->owner;
00581 count++;
00582 }
00583 }
00584 AST_LIST_UNLOCK(&dial->channels);
00585
00586
00587 if (!count) {
00588 set_state(dial, AST_DIAL_RESULT_UNANSWERED);
00589 break;
00590 }
00591
00592
00593 if (dial->thread == AST_PTHREADT_STOP)
00594 break;
00595
00596
00597 who = ast_waitfor_n(cs, pos, &timeout);
00598
00599
00600 if (dial->thread == AST_PTHREADT_STOP)
00601 break;
00602
00603
00604 if (!timeout || !who) {
00605 timeout = handle_timeout_trip(dial, start);
00606 continue;
00607 }
00608
00609
00610 if (!chan || !IS_CALLER(chan, who))
00611 channel = find_relative_dial_channel(dial, who);
00612
00613
00614 if (!ast_strlen_zero(who->call_forward)) {
00615 handle_call_forward(dial, channel, chan);
00616 continue;
00617 }
00618
00619
00620 if (!(fr = ast_read(who))) {
00621
00622 if (chan && IS_CALLER(chan, who)) {
00623 set_state(dial, AST_DIAL_RESULT_HANGUP);
00624 break;
00625 }
00626 if (chan)
00627 ast_poll_channel_del(chan, channel->owner);
00628 ast_hangup(who);
00629 channel->owner = NULL;
00630 continue;
00631 }
00632
00633
00634 if (chan)
00635 handle_frame(dial, channel, fr, chan);
00636 else
00637 handle_frame_ownerless(dial, channel, fr);
00638
00639
00640 ast_frfree(fr);
00641 }
00642
00643
00644 if (dial->state == AST_DIAL_RESULT_ANSWERED) {
00645
00646 AST_LIST_LOCK(&dial->channels);
00647 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00648 if (!channel->owner || channel->owner == who)
00649 continue;
00650 if (chan)
00651 ast_poll_channel_del(chan, channel->owner);
00652 ast_hangup(channel->owner);
00653 channel->owner = NULL;
00654 }
00655 AST_LIST_UNLOCK(&dial->channels);
00656
00657 if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) {
00658 channel->is_running_app = 1;
00659 answer_exec_run(dial, channel, answer_exec->app, answer_exec->args);
00660 channel->is_running_app = 0;
00661 }
00662
00663 if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
00664 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) {
00665 ast_moh_stop(chan);
00666 }
00667 } else if (dial->state == AST_DIAL_RESULT_HANGUP) {
00668
00669 AST_LIST_LOCK(&dial->channels);
00670 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00671 if (!channel->owner)
00672 continue;
00673 if (chan)
00674 ast_poll_channel_del(chan, channel->owner);
00675 ast_hangup(channel->owner);
00676 channel->owner = NULL;
00677 }
00678 AST_LIST_UNLOCK(&dial->channels);
00679 }
00680
00681 return dial->state;
00682 }
00683
00684
00685 static void *async_dial(void *data)
00686 {
00687 struct ast_dial *dial = data;
00688
00689
00690 monitor_dial(dial, NULL);
00691
00692 return NULL;
00693 }
00694
00695
00696
00697
00698
00699 enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
00700 {
00701 enum ast_dial_result res = AST_DIAL_RESULT_TRYING;
00702
00703
00704 if (!dial || (!chan && !async)) {
00705 ast_debug(1, "invalid #1\n");
00706 return AST_DIAL_RESULT_INVALID;
00707 }
00708
00709
00710 if (AST_LIST_EMPTY(&dial->channels)) {
00711 ast_debug(1, "invalid #2\n");
00712 return AST_DIAL_RESULT_INVALID;
00713 }
00714
00715
00716 if (!begin_dial(dial, chan))
00717 return AST_DIAL_RESULT_FAILED;
00718
00719
00720 if (async) {
00721 dial->state = AST_DIAL_RESULT_TRYING;
00722
00723 if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
00724
00725 ast_dial_hangup(dial);
00726 res = AST_DIAL_RESULT_FAILED;
00727 }
00728 } else {
00729 res = monitor_dial(dial, chan);
00730 }
00731
00732 return res;
00733 }
00734
00735
00736
00737
00738
00739 struct ast_channel *ast_dial_answered(struct ast_dial *dial)
00740 {
00741 if (!dial)
00742 return NULL;
00743
00744 return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL);
00745 }
00746
00747
00748
00749
00750
00751 struct ast_channel *ast_dial_answered_steal(struct ast_dial *dial)
00752 {
00753 struct ast_channel *chan = NULL;
00754
00755 if (!dial)
00756 return NULL;
00757
00758 if (dial->state == AST_DIAL_RESULT_ANSWERED) {
00759 chan = AST_LIST_FIRST(&dial->channels)->owner;
00760 AST_LIST_FIRST(&dial->channels)->owner = NULL;
00761 }
00762
00763 return chan;
00764 }
00765
00766
00767
00768
00769
00770 enum ast_dial_result ast_dial_state(struct ast_dial *dial)
00771 {
00772 return dial->state;
00773 }
00774
00775
00776
00777
00778
00779 enum ast_dial_result ast_dial_join(struct ast_dial *dial)
00780 {
00781 pthread_t thread;
00782
00783
00784 if (dial->thread == AST_PTHREADT_NULL)
00785 return AST_DIAL_RESULT_FAILED;
00786
00787
00788 thread = dial->thread;
00789
00790
00791 ast_mutex_lock(&dial->lock);
00792
00793
00794 dial->thread = AST_PTHREADT_STOP;
00795
00796
00797 AST_LIST_LOCK(&dial->channels);
00798 if (AST_LIST_FIRST(&dial->channels)->is_running_app) {
00799 struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner;
00800 if (chan) {
00801 ast_channel_lock(chan);
00802 ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
00803 ast_channel_unlock(chan);
00804 }
00805 } else {
00806
00807 pthread_kill(thread, SIGURG);
00808 }
00809 AST_LIST_UNLOCK(&dial->channels);
00810
00811
00812 ast_mutex_unlock(&dial->lock);
00813
00814
00815 pthread_join(thread, NULL);
00816
00817
00818 dial->thread = AST_PTHREADT_NULL;
00819
00820 return dial->state;
00821 }
00822
00823
00824
00825
00826
00827 void ast_dial_hangup(struct ast_dial *dial)
00828 {
00829 struct ast_dial_channel *channel = NULL;
00830
00831 if (!dial)
00832 return;
00833
00834 AST_LIST_LOCK(&dial->channels);
00835 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00836 if (channel->owner) {
00837 ast_hangup(channel->owner);
00838 channel->owner = NULL;
00839 }
00840 }
00841 AST_LIST_UNLOCK(&dial->channels);
00842
00843 return;
00844 }
00845
00846
00847
00848
00849
00850
00851 int ast_dial_destroy(struct ast_dial *dial)
00852 {
00853 int i = 0;
00854 struct ast_dial_channel *channel = NULL;
00855
00856 if (!dial)
00857 return -1;
00858
00859
00860 AST_LIST_LOCK(&dial->channels);
00861 AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) {
00862
00863 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
00864 if (!channel->options[i])
00865 continue;
00866 if (option_types[i].disable)
00867 option_types[i].disable(channel->options[i]);
00868 channel->options[i] = NULL;
00869 }
00870
00871 if (channel->owner) {
00872 ast_hangup(channel->owner);
00873 channel->owner = NULL;
00874 }
00875
00876 ast_free(channel->tech);
00877 ast_free(channel->device);
00878 AST_LIST_REMOVE_CURRENT(list);
00879 ast_free(channel);
00880 }
00881 AST_LIST_TRAVERSE_SAFE_END;
00882 AST_LIST_UNLOCK(&dial->channels);
00883
00884
00885 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
00886 if (!dial->options[i])
00887 continue;
00888 if (option_types[i].disable)
00889 option_types[i].disable(dial->options[i]);
00890 dial->options[i] = NULL;
00891 }
00892
00893
00894 ast_mutex_destroy(&dial->lock);
00895
00896
00897 ast_free(dial);
00898
00899 return 0;
00900 }
00901
00902
00903
00904
00905
00906
00907
00908 int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
00909 {
00910
00911 if (dial->options[option])
00912 return -1;
00913
00914
00915 if (option_types[option].enable)
00916 dial->options[option] = option_types[option].enable(data);
00917 else
00918 dial->options[option] = (void*)1;
00919
00920 return 0;
00921 }
00922
00923
00924
00925 static struct ast_dial_channel *find_dial_channel(struct ast_dial *dial, int num)
00926 {
00927 struct ast_dial_channel *channel = AST_LIST_LAST(&dial->channels);
00928
00929
00930 if (channel->num == num)
00931 return channel;
00932
00933
00934 AST_LIST_LOCK(&dial->channels);
00935 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00936 if (channel->num == num)
00937 break;
00938 }
00939 AST_LIST_UNLOCK(&dial->channels);
00940
00941 return channel;
00942 }
00943
00944
00945
00946
00947
00948
00949
00950
00951 int ast_dial_option_enable(struct ast_dial *dial, int num, enum ast_dial_option option, void *data)
00952 {
00953 struct ast_dial_channel *channel = NULL;
00954
00955
00956 if (!dial || AST_LIST_EMPTY(&dial->channels))
00957 return -1;
00958
00959 if (!(channel = find_dial_channel(dial, num)))
00960 return -1;
00961
00962
00963 if (channel->options[option])
00964 return -1;
00965
00966
00967 if (option_types[option].enable)
00968 channel->options[option] = option_types[option].enable(data);
00969 else
00970 channel->options[option] = (void*)1;
00971
00972 return 0;
00973 }
00974
00975
00976
00977
00978
00979
00980 int ast_dial_option_global_disable(struct ast_dial *dial, enum ast_dial_option option)
00981 {
00982
00983 if (!dial->options[option]) {
00984 return -1;
00985 }
00986
00987
00988 if (option_types[option].disable)
00989 option_types[option].disable(dial->options[option]);
00990
00991
00992 dial->options[option] = NULL;
00993
00994 return 0;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003 int ast_dial_option_disable(struct ast_dial *dial, int num, enum ast_dial_option option)
01004 {
01005 struct ast_dial_channel *channel = NULL;
01006
01007
01008 if (!dial || AST_LIST_EMPTY(&dial->channels))
01009 return -1;
01010
01011 if (!(channel = find_dial_channel(dial, num)))
01012 return -1;
01013
01014
01015 if (!channel->options[option])
01016 return -1;
01017
01018
01019 if (option_types[option].disable)
01020 option_types[option].disable(channel->options[option]);
01021
01022
01023 channel->options[option] = NULL;
01024
01025 return 0;
01026 }
01027
01028 void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
01029 {
01030 dial->state_callback = callback;
01031 }
01032
01033
01034
01035
01036
01037
01038 void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
01039 {
01040 dial->timeout = timeout;
01041
01042 if (dial->timeout > 0 && (dial->actual_timeout > dial->timeout || dial->actual_timeout == -1))
01043 dial->actual_timeout = dial->timeout;
01044
01045 return;
01046 }
01047
01048
01049
01050
01051
01052
01053
01054 void ast_dial_set_timeout(struct ast_dial *dial, int num, int timeout)
01055 {
01056 struct ast_dial_channel *channel = NULL;
01057
01058 if (!(channel = find_dial_channel(dial, num)))
01059 return;
01060
01061 channel->timeout = timeout;
01062
01063 if (channel->timeout > 0 && (dial->actual_timeout > channel->timeout || dial->actual_timeout == -1))
01064 dial->actual_timeout = channel->timeout;
01065
01066 return;
01067 }