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: 335064 $")
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_INCOMPLETE:
00402 ast_verb(3, "%s dialed Incomplete extension %s\n", channel->owner->name, channel->owner->exten);
00403 ast_indicate(chan, AST_CONTROL_INCOMPLETE);
00404 break;
00405 case AST_CONTROL_RINGING:
00406 ast_verb(3, "%s is ringing\n", channel->owner->name);
00407 if (!dial->options[AST_DIAL_OPTION_MUSIC])
00408 ast_indicate(chan, AST_CONTROL_RINGING);
00409 set_state(dial, AST_DIAL_RESULT_RINGING);
00410 break;
00411 case AST_CONTROL_PROGRESS:
00412 ast_verb(3, "%s is making progress, passing it to %s\n", channel->owner->name, chan->name);
00413 ast_indicate(chan, AST_CONTROL_PROGRESS);
00414 set_state(dial, AST_DIAL_RESULT_PROGRESS);
00415 break;
00416 case AST_CONTROL_VIDUPDATE:
00417 ast_verb(3, "%s requested a video update, passing it to %s\n", channel->owner->name, chan->name);
00418 ast_indicate(chan, AST_CONTROL_VIDUPDATE);
00419 break;
00420 case AST_CONTROL_SRCUPDATE:
00421 if (option_verbose > 2)
00422 ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name);
00423 ast_indicate(chan, AST_CONTROL_SRCUPDATE);
00424 break;
00425 case AST_CONTROL_CONNECTED_LINE:
00426 ast_verb(3, "%s connected line has changed, passing it to %s\n", channel->owner->name, chan->name);
00427 if (ast_channel_connected_line_macro(channel->owner, chan, fr, 1, 1)) {
00428 ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
00429 }
00430 break;
00431 case AST_CONTROL_REDIRECTING:
00432 ast_verb(3, "%s redirecting info has changed, passing it to %s\n", channel->owner->name, chan->name);
00433 if (ast_channel_redirecting_macro(channel->owner, chan, fr, 1, 1)) {
00434 ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen);
00435 }
00436 break;
00437 case AST_CONTROL_PROCEEDING:
00438 ast_verb(3, "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name);
00439 ast_indicate(chan, AST_CONTROL_PROCEEDING);
00440 set_state(dial, AST_DIAL_RESULT_PROCEEDING);
00441 break;
00442 case AST_CONTROL_HOLD:
00443 ast_verb(3, "Call on %s placed on hold\n", chan->name);
00444 ast_indicate(chan, AST_CONTROL_HOLD);
00445 break;
00446 case AST_CONTROL_UNHOLD:
00447 ast_verb(3, "Call on %s left from hold\n", chan->name);
00448 ast_indicate(chan, AST_CONTROL_UNHOLD);
00449 break;
00450 case AST_CONTROL_OFFHOOK:
00451 case AST_CONTROL_FLASH:
00452 break;
00453 case -1:
00454
00455 ast_indicate(chan, -1);
00456 break;
00457 default:
00458 break;
00459 }
00460 }
00461
00462 return;
00463 }
00464
00465
00466 static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr)
00467 {
00468
00469 if (fr->frametype != AST_FRAME_CONTROL)
00470 return;
00471
00472 switch (fr->subclass.integer) {
00473 case AST_CONTROL_ANSWER:
00474 ast_verb(3, "%s answered\n", channel->owner->name);
00475 AST_LIST_LOCK(&dial->channels);
00476 AST_LIST_REMOVE(&dial->channels, channel, list);
00477 AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
00478 AST_LIST_UNLOCK(&dial->channels);
00479 set_state(dial, AST_DIAL_RESULT_ANSWERED);
00480 break;
00481 case AST_CONTROL_BUSY:
00482 ast_verb(3, "%s is busy\n", channel->owner->name);
00483 ast_hangup(channel->owner);
00484 channel->owner = NULL;
00485 break;
00486 case AST_CONTROL_CONGESTION:
00487 ast_verb(3, "%s is circuit-busy\n", channel->owner->name);
00488 ast_hangup(channel->owner);
00489 channel->owner = NULL;
00490 break;
00491 case AST_CONTROL_RINGING:
00492 ast_verb(3, "%s is ringing\n", channel->owner->name);
00493 set_state(dial, AST_DIAL_RESULT_RINGING);
00494 break;
00495 case AST_CONTROL_PROGRESS:
00496 ast_verb(3, "%s is making progress\n", channel->owner->name);
00497 set_state(dial, AST_DIAL_RESULT_PROGRESS);
00498 break;
00499 case AST_CONTROL_PROCEEDING:
00500 ast_verb(3, "%s is proceeding\n", channel->owner->name);
00501 set_state(dial, AST_DIAL_RESULT_PROCEEDING);
00502 break;
00503 default:
00504 break;
00505 }
00506
00507 return;
00508 }
00509
00510
00511 static int handle_timeout_trip(struct ast_dial *dial, struct timeval start)
00512 {
00513 struct ast_dial_channel *channel = NULL;
00514 int diff = ast_tvdiff_ms(ast_tvnow(), start), lowest_timeout = -1, new_timeout = -1;
00515
00516
00517 if (diff >= dial->timeout) {
00518 set_state(dial, AST_DIAL_RESULT_TIMEOUT);
00519 new_timeout = 0;
00520 }
00521
00522
00523 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00524 if (dial->state == AST_DIAL_RESULT_TIMEOUT || diff >= channel->timeout) {
00525 ast_hangup(channel->owner);
00526 channel->owner = NULL;
00527 } else if ((lowest_timeout == -1) || (lowest_timeout > channel->timeout)) {
00528 lowest_timeout = channel->timeout;
00529 }
00530 }
00531
00532
00533 if (lowest_timeout >= 0)
00534 new_timeout = lowest_timeout - diff;
00535
00536 return new_timeout;
00537 }
00538
00539
00540 static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_channel *chan)
00541 {
00542 int timeout = -1;
00543 struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL;
00544 struct ast_dial_channel *channel = NULL;
00545 struct answer_exec_struct *answer_exec = NULL;
00546 struct timeval start;
00547
00548 set_state(dial, AST_DIAL_RESULT_TRYING);
00549
00550
00551 if (dial->options[AST_DIAL_OPTION_RINGING]) {
00552 set_state(dial, AST_DIAL_RESULT_RINGING);
00553 if (chan)
00554 ast_indicate(chan, AST_CONTROL_RINGING);
00555 } else if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
00556 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) {
00557 char *original_moh = ast_strdupa(chan->musicclass);
00558 ast_indicate(chan, -1);
00559 ast_string_field_set(chan, musicclass, dial->options[AST_DIAL_OPTION_MUSIC]);
00560 ast_moh_start(chan, dial->options[AST_DIAL_OPTION_MUSIC], NULL);
00561 ast_string_field_set(chan, musicclass, original_moh);
00562 }
00563
00564
00565 start = ast_tvnow();
00566
00567
00568 timeout = dial->actual_timeout;
00569
00570
00571 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)) {
00572 int pos = 0, count = 0;
00573 struct ast_frame *fr = NULL;
00574
00575
00576 pos = count = 0;
00577 if (chan)
00578 cs[pos++] = chan;
00579
00580
00581 AST_LIST_LOCK(&dial->channels);
00582 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00583 if (channel->owner) {
00584 cs[pos++] = channel->owner;
00585 count++;
00586 }
00587 }
00588 AST_LIST_UNLOCK(&dial->channels);
00589
00590
00591 if (!count) {
00592 set_state(dial, AST_DIAL_RESULT_UNANSWERED);
00593 break;
00594 }
00595
00596
00597 if (dial->thread == AST_PTHREADT_STOP)
00598 break;
00599
00600
00601 who = ast_waitfor_n(cs, pos, &timeout);
00602
00603
00604 if (dial->thread == AST_PTHREADT_STOP)
00605 break;
00606
00607
00608 if (!timeout || !who) {
00609 timeout = handle_timeout_trip(dial, start);
00610 continue;
00611 }
00612
00613
00614 if (!chan || !IS_CALLER(chan, who))
00615 channel = find_relative_dial_channel(dial, who);
00616
00617
00618 if (!ast_strlen_zero(who->call_forward)) {
00619 handle_call_forward(dial, channel, chan);
00620 continue;
00621 }
00622
00623
00624 if (!(fr = ast_read(who))) {
00625
00626 if (chan && IS_CALLER(chan, who)) {
00627 set_state(dial, AST_DIAL_RESULT_HANGUP);
00628 break;
00629 }
00630 if (chan)
00631 ast_poll_channel_del(chan, channel->owner);
00632 ast_hangup(who);
00633 channel->owner = NULL;
00634 continue;
00635 }
00636
00637
00638 if (chan)
00639 handle_frame(dial, channel, fr, chan);
00640 else
00641 handle_frame_ownerless(dial, channel, fr);
00642
00643
00644 ast_frfree(fr);
00645 }
00646
00647
00648 if (dial->state == AST_DIAL_RESULT_ANSWERED) {
00649
00650 AST_LIST_LOCK(&dial->channels);
00651 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00652 if (!channel->owner || channel->owner == who)
00653 continue;
00654 if (chan)
00655 ast_poll_channel_del(chan, channel->owner);
00656 ast_hangup(channel->owner);
00657 channel->owner = NULL;
00658 }
00659 AST_LIST_UNLOCK(&dial->channels);
00660
00661 if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) {
00662 channel->is_running_app = 1;
00663 answer_exec_run(dial, channel, answer_exec->app, answer_exec->args);
00664 channel->is_running_app = 0;
00665 }
00666
00667 if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
00668 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) {
00669 ast_moh_stop(chan);
00670 }
00671 } else if (dial->state == AST_DIAL_RESULT_HANGUP) {
00672
00673 AST_LIST_LOCK(&dial->channels);
00674 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00675 if (!channel->owner)
00676 continue;
00677 if (chan)
00678 ast_poll_channel_del(chan, channel->owner);
00679 ast_hangup(channel->owner);
00680 channel->owner = NULL;
00681 }
00682 AST_LIST_UNLOCK(&dial->channels);
00683 }
00684
00685 return dial->state;
00686 }
00687
00688
00689 static void *async_dial(void *data)
00690 {
00691 struct ast_dial *dial = data;
00692
00693
00694 monitor_dial(dial, NULL);
00695
00696 return NULL;
00697 }
00698
00699
00700
00701
00702
00703 enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
00704 {
00705 enum ast_dial_result res = AST_DIAL_RESULT_TRYING;
00706
00707
00708 if (!dial || (!chan && !async)) {
00709 ast_debug(1, "invalid #1\n");
00710 return AST_DIAL_RESULT_INVALID;
00711 }
00712
00713
00714 if (AST_LIST_EMPTY(&dial->channels)) {
00715 ast_debug(1, "invalid #2\n");
00716 return AST_DIAL_RESULT_INVALID;
00717 }
00718
00719
00720 if (!begin_dial(dial, chan))
00721 return AST_DIAL_RESULT_FAILED;
00722
00723
00724 if (async) {
00725 dial->state = AST_DIAL_RESULT_TRYING;
00726
00727 if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
00728
00729 ast_dial_hangup(dial);
00730 res = AST_DIAL_RESULT_FAILED;
00731 }
00732 } else {
00733 res = monitor_dial(dial, chan);
00734 }
00735
00736 return res;
00737 }
00738
00739
00740
00741
00742
00743 struct ast_channel *ast_dial_answered(struct ast_dial *dial)
00744 {
00745 if (!dial)
00746 return NULL;
00747
00748 return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL);
00749 }
00750
00751
00752
00753
00754
00755 struct ast_channel *ast_dial_answered_steal(struct ast_dial *dial)
00756 {
00757 struct ast_channel *chan = NULL;
00758
00759 if (!dial)
00760 return NULL;
00761
00762 if (dial->state == AST_DIAL_RESULT_ANSWERED) {
00763 chan = AST_LIST_FIRST(&dial->channels)->owner;
00764 AST_LIST_FIRST(&dial->channels)->owner = NULL;
00765 }
00766
00767 return chan;
00768 }
00769
00770
00771
00772
00773
00774 enum ast_dial_result ast_dial_state(struct ast_dial *dial)
00775 {
00776 return dial->state;
00777 }
00778
00779
00780
00781
00782
00783 enum ast_dial_result ast_dial_join(struct ast_dial *dial)
00784 {
00785 pthread_t thread;
00786
00787
00788 if (dial->thread == AST_PTHREADT_NULL)
00789 return AST_DIAL_RESULT_FAILED;
00790
00791
00792 thread = dial->thread;
00793
00794
00795 ast_mutex_lock(&dial->lock);
00796
00797
00798 dial->thread = AST_PTHREADT_STOP;
00799
00800
00801 AST_LIST_LOCK(&dial->channels);
00802 if (AST_LIST_FIRST(&dial->channels)->is_running_app) {
00803 struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner;
00804 if (chan) {
00805 ast_channel_lock(chan);
00806 ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
00807 ast_channel_unlock(chan);
00808 }
00809 } else {
00810
00811 pthread_kill(thread, SIGURG);
00812 }
00813 AST_LIST_UNLOCK(&dial->channels);
00814
00815
00816 ast_mutex_unlock(&dial->lock);
00817
00818
00819 pthread_join(thread, NULL);
00820
00821
00822 dial->thread = AST_PTHREADT_NULL;
00823
00824 return dial->state;
00825 }
00826
00827
00828
00829
00830
00831 void ast_dial_hangup(struct ast_dial *dial)
00832 {
00833 struct ast_dial_channel *channel = NULL;
00834
00835 if (!dial)
00836 return;
00837
00838 AST_LIST_LOCK(&dial->channels);
00839 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00840 if (channel->owner) {
00841 ast_hangup(channel->owner);
00842 channel->owner = NULL;
00843 }
00844 }
00845 AST_LIST_UNLOCK(&dial->channels);
00846
00847 return;
00848 }
00849
00850
00851
00852
00853
00854
00855 int ast_dial_destroy(struct ast_dial *dial)
00856 {
00857 int i = 0;
00858 struct ast_dial_channel *channel = NULL;
00859
00860 if (!dial)
00861 return -1;
00862
00863
00864 AST_LIST_LOCK(&dial->channels);
00865 AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) {
00866
00867 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
00868 if (!channel->options[i])
00869 continue;
00870 if (option_types[i].disable)
00871 option_types[i].disable(channel->options[i]);
00872 channel->options[i] = NULL;
00873 }
00874
00875 if (channel->owner) {
00876 ast_hangup(channel->owner);
00877 channel->owner = NULL;
00878 }
00879
00880 ast_free(channel->tech);
00881 ast_free(channel->device);
00882 AST_LIST_REMOVE_CURRENT(list);
00883 ast_free(channel);
00884 }
00885 AST_LIST_TRAVERSE_SAFE_END;
00886 AST_LIST_UNLOCK(&dial->channels);
00887
00888
00889 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
00890 if (!dial->options[i])
00891 continue;
00892 if (option_types[i].disable)
00893 option_types[i].disable(dial->options[i]);
00894 dial->options[i] = NULL;
00895 }
00896
00897
00898 ast_mutex_destroy(&dial->lock);
00899
00900
00901 ast_free(dial);
00902
00903 return 0;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912 int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
00913 {
00914
00915 if (dial->options[option])
00916 return -1;
00917
00918
00919 if (option_types[option].enable)
00920 dial->options[option] = option_types[option].enable(data);
00921 else
00922 dial->options[option] = (void*)1;
00923
00924 return 0;
00925 }
00926
00927
00928
00929 static struct ast_dial_channel *find_dial_channel(struct ast_dial *dial, int num)
00930 {
00931 struct ast_dial_channel *channel = AST_LIST_LAST(&dial->channels);
00932
00933
00934 if (channel->num == num)
00935 return channel;
00936
00937
00938 AST_LIST_LOCK(&dial->channels);
00939 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00940 if (channel->num == num)
00941 break;
00942 }
00943 AST_LIST_UNLOCK(&dial->channels);
00944
00945 return channel;
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955 int ast_dial_option_enable(struct ast_dial *dial, int num, enum ast_dial_option option, void *data)
00956 {
00957 struct ast_dial_channel *channel = NULL;
00958
00959
00960 if (!dial || AST_LIST_EMPTY(&dial->channels))
00961 return -1;
00962
00963 if (!(channel = find_dial_channel(dial, num)))
00964 return -1;
00965
00966
00967 if (channel->options[option])
00968 return -1;
00969
00970
00971 if (option_types[option].enable)
00972 channel->options[option] = option_types[option].enable(data);
00973 else
00974 channel->options[option] = (void*)1;
00975
00976 return 0;
00977 }
00978
00979
00980
00981
00982
00983
00984 int ast_dial_option_global_disable(struct ast_dial *dial, enum ast_dial_option option)
00985 {
00986
00987 if (!dial->options[option]) {
00988 return -1;
00989 }
00990
00991
00992 if (option_types[option].disable)
00993 option_types[option].disable(dial->options[option]);
00994
00995
00996 dial->options[option] = NULL;
00997
00998 return 0;
00999 }
01000
01001
01002
01003
01004
01005
01006
01007 int ast_dial_option_disable(struct ast_dial *dial, int num, enum ast_dial_option option)
01008 {
01009 struct ast_dial_channel *channel = NULL;
01010
01011
01012 if (!dial || AST_LIST_EMPTY(&dial->channels))
01013 return -1;
01014
01015 if (!(channel = find_dial_channel(dial, num)))
01016 return -1;
01017
01018
01019 if (!channel->options[option])
01020 return -1;
01021
01022
01023 if (option_types[option].disable)
01024 option_types[option].disable(channel->options[option]);
01025
01026
01027 channel->options[option] = NULL;
01028
01029 return 0;
01030 }
01031
01032 void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
01033 {
01034 dial->state_callback = callback;
01035 }
01036
01037
01038
01039
01040
01041
01042 void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
01043 {
01044 dial->timeout = timeout;
01045
01046 if (dial->timeout > 0 && (dial->actual_timeout > dial->timeout || dial->actual_timeout == -1))
01047 dial->actual_timeout = dial->timeout;
01048
01049 return;
01050 }
01051
01052
01053
01054
01055
01056
01057
01058 void ast_dial_set_timeout(struct ast_dial *dial, int num, int timeout)
01059 {
01060 struct ast_dial_channel *channel = NULL;
01061
01062 if (!(channel = find_dial_channel(dial, num)))
01063 return;
01064
01065 channel->timeout = timeout;
01066
01067 if (channel->timeout > 0 && (dial->actual_timeout > channel->timeout || dial->actual_timeout == -1))
01068 dial->actual_timeout = channel->timeout;
01069
01070 return;
01071 }